Context: A customer success team has to onboard “experts”, and those “experts” can have multiple “skills”, modelized via a belongsToMany relationship between “experts” and “skills” tables through an “experts_skills” table; the skills table has ~200 records and experts usually have between 5 to 30 of them.

Unfortunately this is quite painful to edit in forest admin right now since when you want to add a new item in a belongToMany relationship in forest admin you have to:

Intro

In the following we will see how the choice of skills to be added to an expert can be materialized through a searchable smart collection named otherSkills displayed as related data of an expert. An action applicable on the selected records of this collection will allow to associate new skills to an expert.

https://www.loom.com/share/86149f74da524e7499bea4bde5b51e17

Data models

The data models we have been working with here (experts and skills) are the following:

// This model was generated by Lumber. However, you remain in control of your models.
// Learn how here: <https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models>
module.exports = (sequelize, DataTypes) => {
  const { Sequelize } = sequelize;
  // This section contains the fields of your model, mapped to your table's columns.
  // Learn more here: <https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model>
  const Experts = sequelize.define('experts', {
    username: {
      type: DataTypes.STRING,
    },
  }, {
    tableName: 'experts',
    timestamps: false,
    schema: process.env.DATABASE_SCHEMA,
  });

  // This section contains the relationships for this model. See: <https://docs.forestadmin.com/documentation/v/v6/reference-guide/relationships#adding-relationships>.
  Experts.associate = (models) => {
    Experts.belongsToMany(models.skills, {
      through: 'experts_skills',
      foreignKey: 'expert_id',
      otherKey: 'skill_id',
      as: 'expertSkills',
    });
  };

  return Experts;
};
// This model was generated by Lumber. However, you remain in control of your models.
// Learn how here: <https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models>
module.exports = (sequelize, DataTypes) => {
  const { Sequelize } = sequelize;
  // This section contains the fields of your model, mapped to your table's columns.
  // Learn more here: <https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model>
  const Skills = sequelize.define('skills', {
    description: {
      type: DataTypes.STRING,
    },
  }, {
    tableName: 'skills',
    timestamps: false,
    schema: process.env.DATABASE_SCHEMA,
  });

  // This section contains the relationships for this model. See: <https://docs.forestadmin.com/documentation/v/v6/reference-guide/relationships#adding-relationships>.
  Skills.associate = (models) => {
    Skills.belongsToMany(models.experts, {
      through: 'experts_skills',
      foreignKey: 'skill_id',
      otherKey: 'expert_id',
      as: 'skillExperts',
    });
  };

  return Skills;
};

Step 1: create a smart collection 'other skills'

As we already have the skills assigned to an expert as related data when viewing an expert, we'd like to see the skills that have not been assigned and could be by the user.

For this we need to create a smart collection called otherSkills. This smart collection is defined in a file other-skills.js inside the forest folder.