Required Relation Field

Hey,

is it not possible to set a relation field to “required” as with the other field types?

e.g my Blog Collection has a field relation to Categories and Id like that category field to be set/selected to be mandatory.
But the relation field only offers unique and private as options.

Kind regards
Luca

Hello,

Currently its not possible. Git Issue

Thanks :slight_smile:

For those interested, there is a work-around for this (at least for my requirements):

(As mentioned in Specify relation column as required · Issue #557 · strapi/strapi · GitHub by ByungJun25)

If you want to enforce the user settings one or more relationships before the entity is saved, you can implement appropriate lifecycle methods (e.g. beforeCreate and beforeUpdate) for the model and throw an error if the relationship has not been set in the data/params that are passed into the methods. If you want to be able to set the error message you have to use the boom module to create a Boom error. e.g.:

const Boom = require('boom');
...

const err = new Error("Some useful message about the missing relation");
const boomError = Boom.boomify(err, {
  statusCode: 422,
});
throw(boomError);

Obviously, this did not enforce at the database level - so manual sql inserts would still succeed.

Hope this helps someone

Hi Hunter ! Thank you for your work-around. I would like apply this only when I’m in a ‘publish’ mode (not in draft mode). I don’t know how I get the document’s status value by using lifecycle methods… Do you have an idea ?

Thank you

Hey @Jordan,

You should be able to look at the published_at property of the data argument for beforeCreate / beforeUpdate.

If published_at is null (for beforeCreate) or not set (for beforeUpdate) then the save is for a draft.

If the data argument for beforeUpdate has published_at with a valid date then the entity is being published (The Publish button was pressed). However, as you don’t get the entity’s other attributes passed in via data, you will probably have to load the existing entity (using the id from the params arg) and then check the relationship(s) that you want to enforce.

@hunter,

Thank you so much for your quickly feedback and for your help !
Everything works fine for me with your recommendations !

Best regards.

1 Like

Hi @hunter,

I tried to implement an check for a required relation for the article-category in the article-model with your advices but I won’t work the right way.

async beforeUpdate(params, data) {
      const article = await strapi.query('article').find({id: params.id});

      if(article[0].article_category === undefined || article[0].article_category === null) {
        throw new Error('Entity is required!');
      }
    }, 

I tried to get the article and then check if the relation to article_category is defined.

Generally it’s really hard for me to debug the lifecycle-code. I insert some console.log but I don’t see them in browser or postman. Do you have any tip how to debug these hooks to see the console.log?

Best regards,

Timo

Hi @iparker,

For debugging any Strapi server-side code I do the following (it gives you a full debugging experience):

  1. Use VSCode to open the project

  2. Open the terminal panel in VSCode (Terminal->New Terminal)

  3. On the Top Righthand side from the dropdown menu, select “Create JavaScript Debug Terminal”
    Screen Shot 2021-02-05 at 9.40.53 AM

  4. From that terminal run yarn strapi:develop

  5. Open the javascript file and set a breakpoint (click in the left margin next to the line number) - a red dot will appear
    Screen Shot 2021-02-05 at 9.48.51 AM

  6. Call the lifecycle event (via the browser or Postman etc)

  7. The debugger will pause at the breakpoint and you can inspect all the variables, stack, etc.

Just a note:

  1. The console events will be shown via the terminal that you use to run strapi (e.g. yarn strap:develop)
  2. The example code you have looks like it is for a model that has draft publishing enabled. If you are not using draft, then you should check the data object directly for the relation(s). If you are using draft, you should check to see if the data is just the publish date (see previous comments I made)
  3. If you only want to load one record, you can use .findOne(:id)
  4. There are other ways to debug the server-side code, but I think this is the easiest to setup.

Hope this helps :slight_smile:

Thanks a lot for your detailed explanation. I will check the debugging soon.

For my example code: Yes this is a model with publishing enabled. After your feedback I tried the following code and it seems to work:

async beforeUpdate(params, data) {
      if(data.published_at && !data.title) {

        const article = await strapi.query('article').find({id: params.id});

        if(article[0].article_category === undefined || article[0].article_category === null) {
           throw new Error('Entity is required!');
        }
      }
      else if(!data.published_at && data.title) {
        if(data.article_category === undefined || data.article_category === null) {
          throw new Error('Entity is required!');
        }
      }
    },

Or do you see any mistake in it?

Thanks for your help!

Hi, guys. Thank you all. This topic was very helpful for me.

async beforeUpdate(params, data) {
  const news = await strapi.query("news-item").findOne({ id: params.id });
  const newsUpdated = { ...news, ...data };

  if (newsUpdated.published_at != null) {
    if (newsUpdated.user == null) {
      const err = new Error("Please set up User field");
      const boomError = Boom.boomify(err, {
        statusCode: 422,
      });
      throw boomError;
    }
  }
}

As @hunter says, I use Boom for error message in admin panel. But who can tell me, how can i hightlight that wrong field with red border or something like that?