Smart action form with default related value

Hello, I would like to know if it is possible to put a default value to a related field on a smart action form.

It would look like something like this :

Sadly, the “Categorie” and “Sous_categorie” inputs are empty by default.

Expected behavior

I would like the “Categorie” and “Sous_categorie” inputs to be filled by default with the existing values.

Actual behavior

These 2 inputs are empty

Failure Logs

No failure logs

Code

Here’s the forest file :

const { collection } = require('forest-express-sequelize');
const { demandeAjoutModele, categorie, sousCategorie } = require('../models');
const _ = require('lodash');

collection('demandeAjoutModele', {
  actions: 
  [
    {
      name: 'Accepter',
      type: 'single',
      endpoint: '/forest/accepter',
      fields: 
      [
        {
          field: 'marque',
          description: 'La marque du modèle (exemple: Sony)',
          type: 'String',
          isRequired: true
        }, 
        {
          field: 'modele',
          description: 'Le nom complet du modèle (exemple: Alpha 7S II)',
          type: 'String',
          isRequired: true
        },
        {
          field: 'categorie',
          reference: 'categorie.id',
          isRequired: true
        },
        {
          field: 'sous_categorie',
          reference: 'sousCategorie.id',
          isRequired: true
        },
      ],
      hooks: {
        load: async ({ fields, request }) => {
          const marqueField = fields.find(field => field.field === 'marque');
          const modeleField = fields.find(field => field.field === 'modele');
          const categorieField = fields.find(field => field.field === 'categorie');
          const sousCategorieField = fields.find(field => field.field === 'sous_categorie')
          
          const id = request.body.data.attributes.ids[0];
          const demande = await demandeAjoutModele.findByPk(id);

          const categorieEntity = await categorie.findOne({where: { id: demande.dataValues.categorieId }})
          const sousCategorieEntity = await sousCategorie.findOne({where: { id: demande.dataValues.sousCategorieId }})

          console.log(categorieEntity);
          console.log(sousCategorieEntity);

          categorieField.value = categorieEntity;
          sousCategorieField.value = sousCategorieEntity;
          marqueField.value = demande.marque;
          modeleField.value = demande.modele;
          
          return fields;
        },
      },
      
    },
  ],
  fields: [],
  segments: [],
});

Thanks for your help :grinning:

Hello @KLassiux,

Welcome to the Forest Admin community :tada:

Could you share with me the version of the forest-express-sequelize library you are using please?
Also what do you see in your console.log?

Thank you,

Hello Guillaume :grinning:
I am currently using the version 8.0.5 of the forest-express-sequelize library

In the console, all I see is this :

lightyshare_v_2  | POST /forest/actions/accepter/hooks/load?timezone=Europe%2FParis 200 915 - 29.489 ms

I also tried like this :

 hooks: {
        load: async ({ fields, request }) => {
          const marqueField = fields.find(field => field.field === 'marque');
          const modeleField = fields.find(field => field.field === 'modele');
          const categorieField = fields.find(field => field.field === 'categorie');
          const sousCategorieField = fields.find(field => field.field === 'sous_categorie')
          
          const id = request.body.data.attributes.ids[0];
          const demande = await demandeAjoutModele
          .findOne({ where: { id: id }, include: [{ model: categorie, as: 'categorie' }, { model: sousCategorie, as: 'sousCategorie'}]});

          marqueField.value = demande.marque;
          modeleField.value = demande.modele;
          categorieField.value = demande.categorie;
          sousCategorieField.value = demande.sousCategorie;
          
          return fields;
        },
      },

But same result :confused:

Do you have anything with console.log too?

Oh right, sorry, yeah, it’s returning me the categorie and the sousCategorie

lightyshare_v_2  | categorie {
lightyshare_v_2  |   dataValues: { id: 1, nom: 'Vidéo / Photo' },
lightyshare_v_2  |   _previousDataValues: { id: 1, nom: 'Vidéo / Photo' },
lightyshare_v_2  |   _changed: {},
lightyshare_v_2  |   _modelOptions:
lightyshare_v_2  |    { timestamps: false,
lightyshare_v_2  |      validate: {},
lightyshare_v_2  |      freezeTableName: false,
lightyshare_v_2  |      underscored: false,
lightyshare_v_2  |      paranoid: false,
lightyshare_v_2  |      rejectOnEmpty: false,
lightyshare_v_2  |      whereCollection: { id: 1 },
lightyshare_v_2  |      schema: null,
lightyshare_v_2  |      schemaDelimiter: '',
lightyshare_v_2  |      defaultScope: {},
lightyshare_v_2  |      scopes: {},
lightyshare_v_2  |      indexes: [],
lightyshare_v_2  |      name: { plural: 'categories', singular: 'categorie' },
lightyshare_v_2  |      omitNull: false,
lightyshare_v_2  |      tableName: 'categorie',
lightyshare_v_2  |      sequelize:
lightyshare_v_2  |       Sequelize {
lightyshare_v_2  |         options: [Object],
lightyshare_v_2  |         config: [Object],
lightyshare_v_2  |         dialect: [MysqlDialect],
lightyshare_v_2  |         queryInterface: [QueryInterface],
lightyshare_v_2  |         models: [Object],
lightyshare_v_2  |         modelManager: [ModelManager],
lightyshare_v_2  |         connectionManager: [ConnectionManager],
lightyshare_v_2  |         importCache: [Object] },
lightyshare_v_2  |      hooks: {} },
lightyshare_v_2  |   _options:
lightyshare_v_2  |    { isNewRecord: false,
lightyshare_v_2  |      _schema: null,
lightyshare_v_2  |      _schemaDelimiter: '',
lightyshare_v_2  |      raw: true,
lightyshare_v_2  |      attributes: [ 'id', 'nom' ] },
lightyshare_v_2  |   isNewRecord: false }
lightyshare_v_2  | sousCategorie {
lightyshare_v_2  |   dataValues:
lightyshare_v_2  |    { id: 1,
lightyshare_v_2  |      categorieId: 1,
lightyshare_v_2  |      nom: 'Caméras cinéma numérique',
lightyshare_v_2  |      preciseCate: null,
lightyshare_v_2  |      aLaUne: null,
lightyshare_v_2  |      picture: null },
lightyshare_v_2  |   _previousDataValues:
lightyshare_v_2  |    { id: 1,
lightyshare_v_2  |      categorieId: 1,
lightyshare_v_2  |      nom: 'Caméras cinéma numérique',
lightyshare_v_2  |      preciseCate: null,
lightyshare_v_2  |      aLaUne: null,
lightyshare_v_2  |      picture: null },
lightyshare_v_2  |   _changed: {},
lightyshare_v_2  |   _modelOptions:
lightyshare_v_2  |    { timestamps: false,
lightyshare_v_2  |      validate: {},
lightyshare_v_2  |      freezeTableName: false,
lightyshare_v_2  |      underscored: true,
lightyshare_v_2  |      paranoid: false,
lightyshare_v_2  |      rejectOnEmpty: false,
lightyshare_v_2  |      whereCollection: { id: 1 },
lightyshare_v_2  |      schema: null,
lightyshare_v_2  |      schemaDelimiter: '',
lightyshare_v_2  |      defaultScope: {},
lightyshare_v_2  |      scopes: {},
lightyshare_v_2  |      indexes: [],
lightyshare_v_2  |      name: { plural: 'sousCategories', singular: 'sousCategorie' },
lightyshare_v_2  |      omitNull: false,
lightyshare_v_2  |      tableName: 'sous_categorie',
lightyshare_v_2  |      sequelize:
lightyshare_v_2  |       Sequelize {
lightyshare_v_2  |         options: [Object],
lightyshare_v_2  |         config: [Object],
lightyshare_v_2  |         dialect: [MysqlDialect],
lightyshare_v_2  |         queryInterface: [QueryInterface],
lightyshare_v_2  |         models: [Object],
lightyshare_v_2  |         modelManager: [ModelManager],
lightyshare_v_2  |         connectionManager: [ConnectionManager],
lightyshare_v_2  |         importCache: [Object] },
lightyshare_v_2  |      hooks: {} },
lightyshare_v_2  |   _options:
lightyshare_v_2  |    { isNewRecord: false,
lightyshare_v_2  |      _schema: null,
lightyshare_v_2  |      _schemaDelimiter: '',
lightyshare_v_2  |      raw: true,
lightyshare_v_2  |      attributes:
lightyshare_v_2  |       [ 'id', 'categorieId', 'nom', 'preciseCate', 'aLaUne', 'picture' ] },
lightyshare_v_2  |   isNewRecord: false }

Ok I think you need to serialize these sequelize Models thanks to the JSON Api.

I will test this on my way and let you know :slight_smile:

Thank you so much :slight_smile:, i’m a newbie with Javascript and Sequelize :grinning_face_with_smiling_eyes:

Oh, and I had another question. As you can see in the first screenshot that I posted, there’s a ‘Marque’ attribute that has no relations with another table. But in reality, I have a table called ‘marque’ (brand in english). Is it possible to search if the marque exists in the table marque ? If it does it would do just like for the Categorie or Sous_categorie inputs. If not, it would create a new marque.
I already did that in the route file with just a condition (if findOne where name then it exists; else create a new one).
I don’t know if i’m clear with what I said…

Okay, I’ve serialized the data, here it is :

lightyshare_v_2  | { data:
lightyshare_v_2  |    { type: 'categories',
lightyshare_v_2  |      id: '1',
lightyshare_v_2  |      attributes: { nom: 'Vidéo / Photo' } } }
lightyshare_v_2  | { data:
lightyshare_v_2  |    { type: 'sousCategories',
lightyshare_v_2  |      id: '1',
lightyshare_v_2  |      attributes: { nom: 'Caméras cinéma numérique' } } }

But I still can’t show it in the input

After some discussion with my team, you should put the id as the value, not the whole object (serialized or not).

Let me know if it works :wink:

Yup, that’s what I did at the beginning (I even tried to console log the foreign keys to see if it printed out correctly and it did) but still, nothing, that’s strange :confused:

We’ve detected a regression on our web application with related data and load hook.
We are working on a fix, we will let you know when it is available :smiley:

I’ll keep you updated :rocket:

1 Like

Hi @KLassiux :wave: a fix have been released.
Can you confirm this fixed your issue ?