Conditional data stored in Mongo

default discord avatar
Trstly
2 months ago
20

I have a group called exampleGroup with two conditionals on select field example. When creating the collection, all is fine (fig 1).



The problem is on an update. It doesn't replace but adds the data like in below (fig 2).



How do I update the data so the result is like fig 1 exampleGroup? I have tried to add a hook to the group field, but I can't get I working.




fig 1:



{
  "id": "6429688e7f347a304b7de975",
  "title": "Test",
  "example": "example1",
  "exampleGroup": {
    "conditional1": [
      "conditional11"
    ],
    "conditional2": []
  },
  "_status": "published",
  "createdAt": "2023-04-02T11:35:42.583Z",
  "updatedAt": "2023-04-02T11:35:42.583Z"
}


fig 2:


{
  "id": "6429688e7f347a304b7de975",
  "title": "Test",
  "example": "example2",
  "exampleGroup": {
    "conditional1": [
      "conditional11"
    ],
    "conditional2": [
      "conditional22"
    ]
  },
  "_status": "published",
  "createdAt": "2023-04-02T11:35:42.583Z",
  "updatedAt": "2023-04-02T11:37:20.613Z"
}


Collection:


 
{
  slug: "conditions",
  admin: {
    useAsTitle: "title",
    defaultColumns: ["title", "createdAt", "updatedAt"],
    group: "Examples",
  },
  versions: {
    drafts: true,
  },

  access: {
    read: () => true,
  },

  fields: [
    {
      name: "title",
      type: "text",
      required: true,
      localized: true,
    },

    {
      type: "select",
      name: "example",
      required: true,

      options: [
        {
          label: "Example One",
          value: "example1",
        },
        {
          label: "Example Two",
          value: "example2",
        },
      ],
    },

    {
      name: "exampleGroup",
      type: "group",

      fields: [
        {
          name: "conditional1",
          label: "Conditional One",
          type: "select",
          hasMany: true,
          admin: {
            condition: ({ example }) => example === "example1",
          },
          options: [
            {
              label: "Conditional.1 One",
              value: "conditional11",
            },
            {
              label: "Conditional.1 Two",
              value: "conditional12",
            },
          ],
        },
        {
          name: "conditional2",
          label: "Conditional One",
          type: "select",
          hasMany: true,
          admin: {
            condition: ({ example }) => example === "example2",
          },
          options: [
            {
              label: "Conditional.2 One",
              value: "conditional21",
            },
            {
              label: "Conditional.2 Two",
              value: "conditional22",
            },
          ],
        },
      ],
    },
  ],
}
  • default discord avatar
    Alessio 🍣
    2 months ago

    Can you share how you currently update the data? And can you also share (1) the state before the update, (2) the state after the update and (3) what you would expect it to look like instead?



    I think that would make it a little clearer!

  • default discord avatar
    Trstly
    2 months ago

    Yes, the collection as above creates the data. It should be a working collection with an example select field and two conditional select fields. Fig 1 is the state after the first creation, and fig 2 is after conditional12 is created. Then I expected the result to be replaced with the following:



    {
      "id": "6429688e7f347a304b7de975",
      "title": "Test",
      "example": "example2",
      "exampleGroup": {
        "conditional2": [
          "conditional22"
        ]
      },
      "_status": "published",
      "createdAt": "2023-04-02T11:35:42.583Z",
      "updatedAt": "2023-04-02T11:37:20.613Z"
    }


    And not as in fig 2 as is currently the case.

  • default discord avatar
    Alessio 🍣
    2 months ago

    @Trstly can you also test if it happens in payload v1.6.29? There has been a change regarding updating group fields of collection last week



    Also, could you share how exactly you did the update?

  • default discord avatar
    Trstly
    2 months ago

    The version is v1.6.29.



    select Example One then save=create, then select Example Two then save=update. Now data = fig 2 not reflecting the selection of the ui.

  • default discord avatar
    Alessio 🍣
    2 months ago

    Ah I think I know what you mean. So you mean just the Admin UI - not any Rest API update.



    I think you expect the conditional field to be automatically unselected / nul'led if the condition is not true anymore, right?



    The condition only affects the admin UI, though - that's why it's in the admin{} option. It doesn't affect the actual data / it doesn't "clear" the data when it's not true anymore.



    Someone correct me if I'm wrong, but manually clearing the data if the condition isn't met using the

    beforeUpdate

    hook would probably do what you want it to do!

  • default discord avatar
    Trstly
    2 months ago

    Exactly right. I tried hooks beforeOperation, beforeValidate, beforeChange on the group, and it is not working. How do I use beforeUpdate?

  • default discord avatar
    Alessio 🍣
    2 months ago

    Oh sorry, I did mean beforeChange!



    Basically it passes the current data to your beforeChange hook. There you remove the data for the group where the condition is not fulfilled anymore, and return the new data.



    The data you return in the beforeChange hook will modify the collection/field!

  • default discord avatar
    Trstly
    2 months ago

    I added this hook to the group, but it's not working:



    const beforeChange: FieldHook = async ({
      data,
      value,
    }) => {
    
      if(data) {
      
        return  { [data.example]: data.exampleGroup[data.example] };
      }
    
      return value
    }
    
    
    {
      slug: "conditions",
      admin: {
        useAsTitle: "title",
        defaultColumns: ["title", "createdAt", "updatedAt"],
        group: "Examples",
      },
      versions: {
        drafts: true,
      },
    
      access: {
        read: () => true,
      },
    
      fields: [
        {
          name: "title",
          type: "text",
          required: true,
          localized: true,
        },
    
        {
          type: "select",
          name: "example",
          required: true,
    
          options: [
            {
              label: "Example One",
              value: "conditional1",
            },
            {
              label: "Example Two",
              value: "conditional2",
            },
          ],
        },
    
        {
          name: "exampleGroup",
          type: "group",
          hooks: {
            beforeChange: [beforeChange]
          },
          fields: [
            {
              name: "conditional1",
              label: "Conditional One",
              type: "select",
              hasMany: true,
              admin: {
                condition: ({ example }) => example === "conditional1",
              },
              options: [
                {
                  label: "Conditional.1 One",
                  value: "conditional11",
                },
                {
                  label: "Conditional.1 Two",
                  value: "conditional12",
                },
              ],
            },
            {
              name: "conditional2",
              label: "Conditional One",
              type: "select",
              hasMany: true,
              admin: {
                condition: ({ example }) => example === "conditional2",
              },
              options: [
                {
                  label: "Conditional.2 One",
                  value: "conditional21",
                },
                {
                  label: "Conditional.2 Two",
                  value: "conditional22",
                },
              ],
            },
          ],
        },
      ],
    }
  • default discord avatar
    Alessio 🍣
    2 months ago
    const beforeChange: FieldHook = async ({
      data,
      value,
    }) => {
    
      if(data?.example === "conditional1"){
        value.conditional2 = [];
      } else if(data?.example === "conditional2"){
        value.conditional1 = [];
      }
      
      return value
    }

    Maybe try something like that for the hook @Trstly (didn't test it)



    "data" should be the data from the entire document, "value" should be the value from just the group you added the hook too - which will make things easier!

  • default discord avatar
    Trstly
    2 months ago

    That works because it is an empty array modifying the value, but I wanted to delete the unused key, which may be impossible?



    My version returns: { conditional1: [ 'conditional11' ] }


    Your version returns: { conditional1: [ 'conditional11' ], conditional2: [] }

  • default discord avatar
    Alessio 🍣
    2 months ago

    in that case just set it to null instead of [] 🙂

  • default discord avatar
    Trstly
    last month
    ` {   "id": "6429688e7f347a304b7de975",   "title": "Test",   "example": "conditional2",   "exampleGroup": {     "conditional1": null, // I want this deleted :-D, not [] or null. Is that possible?     "conditional2": [       "conditional21"     ]   },   "_status": "published",   "createdAt": "2023-04-02T11:35:42.583Z",   "updatedAt": "2023-04-03T13:38:34.283Z" }


    thank you for all you help!

  • default discord avatar
    Alessio 🍣
    last month

    hmm good question, what happens if you set it to undefined?

  • default discord avatar
    Trstly
    last month

    Then the data don't update, and are the previous successfully added values



    Does anybody know about setting selects and relationships to null if the condition returns false? Or overriding setValue without creating a new component?



    It could save many if sentences and prevent hidden conditional fields from being committed to mongo

Open the post
Continue the discussion in Discord
Like what we're doing?
Star us on GitHub!

Star

Connect with the Payload Community on Discord

Discord

online

Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.