Create Conditional Content Field

We have a collection called “articles”, and we need to add a new field to it, that will comprise of:

  • A boolean flag
  • A dropdown list, populated by a related collection

We need the form to disable the dropdown field, unless the boolean flag has been set to True.

To do this, I believe we need to override some functionality in the content-manager plug-in by adding files to the equivalent location in the extensions folder. However, I’m having some difficulty figuring out where in the content-manager plug-in I would add a new field type.

Is anyone able to point me in the right direction?

Thanks very much.

1 Like

Hello!

I am guessing that this behaviour is wanted in one particular content type in your application, so here’s my thought about your case:

Personally, I would consider overriding the relation component of the content manager (it’s the SelectWrapper) by modifying the logic that disables a field. I order to do this you can modify 2 files:

  1. /content-manager/admin/src/components/SelectWrapper/utils/select.js:
const {
    isCreatingEntry,
    createActionAllowedFields,
    readActionAllowedFields,
    slug,
    updateActionAllowedFields,
    modifiedData,
  } = useDataManager();

  const isAttachedBooleanFieldValueChecked = useMemo(() => {
    // Replace with the correct attribute name
    return get(modifiedData, ["<name_of_the_boolean_field>"], false);
  }, [modifiedData]);

  const isFieldAllowed = useMemo(() => {
    if (
      slug === "application::<name_of_the_collection_type>" &&
      name === "<name_of_relations>" &&
      !isAttachedBooleanFieldValueChecked
    ) {
      return false;
    }

    if (isUserAllowedToEditField === true) {
      return true;
    }

    const allowedFields = isCreatingEntry
      ? createActionAllowedFields
      : updateActionAllowedFields;

    return allowedFields.includes(name);
  }, [
    isCreatingEntry,
    createActionAllowedFields,
    name,
    slug,
    isAttachedBooleanFieldValueChecked,
    isUserAllowedToEditField,
    updateActionAllowedFields,
  ]);

In this file we have just update the logic that makes a field disabled or not.

  1. You will need to make a minor update to the index.js of this component to update the dependencies array of the useMemo hook.
// Find the corresponding code for the isDisabled constant and add isFieldAllowed and isFieldReadable to the array of dependencies.

const isDisabled = useMemo(() => {
    if (isMorph) {
      return true;
    }

    if (!isCreatingEntry) {
      return (!isFieldAllowed && isFieldReadable) || !editable;
    }

    return !editable;
  }, [isMorph, isCreatingEntry, editable, isFieldAllowed, isFieldReadable]);

Normally with this little override you will achieve what you are trying to do.

5 Likes

Thanks so much for the detailed response - that’s great.

To provide some context, our use-case is that we sometimes sell a “sponsored” article. When we do, we need to set a flag to say that the article is sponsored (the Boolean flag). Additionally, when this is selected, we need to select the sponsor from a list of businesses that we work with (the select list).

My only concern with your solution is that it would effect all relations we have on the collection schema (or in fact, every collection schema?). There are several other relations that would be in the same collection schema that we would not want to be disabled by the value of the Boolean field.

So would we need to create this as a new component / field type? If so, is there anything additional we would need to do?

1 Like

My only concern with your solution is that it would effect all relations we have on the collection schema (or in fact, every collection schema?). There are several other relations that would be in the same collection schema that we would not want to be disabled by the value of the Boolean field.

Normally you will a unique name of the relation so the following condition: slug === "application::<name_of_the_collection_type>" && name === "<name_of_relation>" should be unique in your application as you can only have one content type that matches applicaton::article.article and a unique field sponsor.

3 Likes

Thanks very much. We’ll give that a go.

2 Likes

For clarification on this, you will want to use extensions so the path would be ./extensions/content-manager/admin/src/components/SelectWrapper/utils/select.js and copying in the original content from: https://github.com/strapi/strapi/blob/master/packages/strapi-plugin-content-manager/admin/src/components/SelectWrapper/utils/select.js

Same would apply for any customization of a plugin :wink:

3 Likes

Hello Guys
Thanks you for theses tips.

I was wondering if this could work with the media field on the upload plugin ?

Hi, everyone.

Who can tell me how can i implement that feature for Input fields? There is no name property in select.js

I add ./extensions/content-manager/admin/src/components/SelectWrapper/utils/select.js but I found that the name is deprecated. Any suggestion?


With “strapi”: “3.5.4”, after copying the contents of **https://github.com/strapi/strapi/blob/master/packages/strapi-plugin-content-manager/admin/src/components/SelectWrapper/index.**js to extensions/content-manager/admin/src/components/SelectWrapper/index.js

I get the following error ReferenceError: get is not defined can anyone help?

1 Like

Maybe some difference between github files and your installed version.
I’m copy files from node_modules
I’m inserting these strings to package.json :

"copy": "copyfiles -f ./node_modules/strapi-plugin-content-manager/admin/src/components/SelectWrapper/*.* ./extensions/content-manager/admin/src/components/SelectWrapper",

    "copy5": "copyfiles -f ./node_modules/strapi-plugin-content-manager/admin/src/components/SelectWrapper/utils/*.* ./extensions/content-manager/admin/src/components/SelectWrapper/utils",
    "

Strapi 3.6.3

Same issue here. This solution doesn’t seem to work anymore.

I have this working in V3 but I’m now using V4 for the first time and trying to implement the same update, can anyone advise on how the equivalent would work in v4? I’m a little lost on where the files for SelectWrapper/index would live

5 Likes