Make belongsTo fields editable in smart collections

Dear sirs,
I’ve been trying to figure out how to edit a field in a smart relationship as part of the same PUT call I’m already using to edit the info or the main table, but I want to make it without an additional call, as it follows:

PUT forest/main_table/1/relationships/category

So here is the situation: I need to edit the name and the category of main_table.
Main table have a smart relationship with category table, so I added a field as it follows to the smart collection:

{
      field: 'category',
      type: 'String',
      reference: 'category.id'
}

So, getting back to the example, I need to change both the name and the category at the same time, but I don’t want to handle the logic in 2 separate calls (one for the fields of the main table and one for the relationship).

Is there a way to do that? It would be particularly beneficial when I have many relationships in a given smart collection. So is there a way to only fire a call like this PUT forest/main_table?

Thank you so much in advance.

Best,
Gabriele

Hello @Gabriele,

I’m not sure to understand your use case here. You are trying to create a HasMany Smart Relationship (1-N)?

In this case, the front end will try to call PUT forest/main_table/:id/relationships/category for each category that belongs to main table record (as you can have multiples categories per main table record).

On another hand, the only way to handle this in the same call is to have a BelongTo relationship (1-1) between main_table and category, in this case, you can simply use a smart field in the main table collection directly. (UPDATE: You still need to implement the relationship route)

Let me know if it helps.

Kind regards,
Morgan

@morganperre thank you for the kind reply.
Yes, in fact what I was trying to achieve is a 1-1 belongsTo relationship.

import { collection } from 'forest-express-sequelize';

collection('main_table', {
  isSearchable: true,
  fields: [
    ...
    {
      field: 'category',
      type: 'String',
      reference: 'category.id',
    },
  ],
  actions: [],
  segments: [],
});

Here is how I declared. And when I edit I can see the dropdown with all the categories, but when I save, it tries to call a PUT forest/main_table/:id/relationships/category, which shouldn’t happen, if I understand correctly. In fact, I would expect to have it all in a single PUT call to PUT forest/main_table/:id.

P.s. note the both main_table and category are smart collections.

Am I doing something wrong?

Hello @Gabriele,

Ok, much more clear to me, I thought you were creating a HasMany Smart Relationship…

Can you share your screen with the main_table, I would love to see where category is (in the details or in the related data) ?

I think you should add the get of the category field, you can find some documentation, on you to do this in an optimize way.

(UPDATE: You still need to implement the relationship route)

Kind regards,
Morgan

@morganperre here it is. However, I noticed that the “category” does not seem to be clickable.
I’m wondering if I need some particular setup on the route.

Screenshot 2022-03-25 at 17.21.45

The route basically does something like this by now:

import { RecordSerializer } from 'forest-express-sequelize';

...

router.get('/main_table', permissionMiddlewareCreator.list(), async (req, res) => {
   return res.send(
      new RecordSerializer('assets').serialize([
         {
            id: 1,
            icon: '',
            symbol: 'AAPL',
            category: {
              id: 1,
              name: 'Category'
            }
         },
         {
            id: 2,
            icon: '',
            symbol: 'MSFT',
            category: {
              id: 1,
              name: 'Category'
            }
         }
      ])
   );
});

I also tried to only pass category: 1, but it didn’t show anything.

How should I proceed?

Hello @Gabriele,

If you want to serialize BelongTo relationship you simply need to pass the id of the related data to the serializer. You can find an example here but that the manual way to do it.

import { RecordSerializer } from 'forest-express-sequelize';
...

router.get('/main_table', permissionMiddlewareCreator.list(), async (req, res) => {
   return res.send(
      new RecordSerializer('assets').serialize([
         {
            id: 1,
            icon: '',
            symbol: 'AAPL',
            category: {
              id: 1,
            }
         },
         {
            id: 2,
            icon: '',
            symbol: 'MSFT',
            category: {
              id: 1,
            }
         }
      ])
   );
});

Depending of your use case, it can be handy to use a custom get on the smart field itself so the relation is automatically handled.

Let me know if it helps.

Kind regards,
Morgan

Ok I tried and it works, but again when I try to edit, is sends a PUT to the wrong path.

Here’s the response I get for each main_table. So it’s as if during the serialization it’s considering a one-to-many relation instead of a one-to-one.

relationships: {
data: {type: "category", id: "1"}
links: {related: {href: "/forest/assets/1/relationships/category"}

Ok. There might be a wrong synchronization of your code or forestadmin-schema.json here. Can you share your project name and environment so I can check your collections definitions on my end ?

Regards,
Morgan

Thank you so much!
It’s Emma/staging.

The collection names are asset and asset_category!

Hello @Gabriele,

I re-tested everything on my own and indeed you cannot handle the BelongsTo Smart Relationship by using the set hook on the Smart Field. You indeed need to create a specific route to handle your BelongsTo Smart Relationship edition. So, unfortunately, you cannot have just one call to handle this.

See this doc on the relationship route to extends/implement so specific use case.

PUT /forest/{modelName}/{id}/relationships/{belongsToRelationName} ⟶ Update a belongs to field

Here, is another thread that gives an example of BelongsTo Smart Relationship full implementation.

I apologize for the wrong information I gave you first. :pray:

Tell me if you need more help to make it work on your project.

Kind regards,
Morgan