Get value from JSON when plugin is used (onBeforeItemUpsert)

Hi,

I’m currently struggling with how to retrieve the correct values when using a JSON field with a plugin attached to it. I’m using the onBeforeItemUpsert hook with the code example from the docs but it only describes a “simple” case with a fixed name and a small tree to get the value to be handled.

This is my code but it’s linked to a specific setup within my project (a model with a modular content field called “sections”)… Is there a better way?

onBeforeItemUpsert(createOrUpdateItemPayload, ctx): any {
      const entitySelectorFieldAttributes = Object.values(ctx.fields).find(
        (field) => field?.attributes.appearance.field_extension === "entitySelector",
      )?.attributes;

      if (typeof entitySelectorFieldAttributes === "undefined") {
        return; // no plugin was used
      }

      for (const locale of ctx.site.attributes.locales) {
        const sectionsFieldPath = `data.attributes.sections.${locale}`;
        const sectionsJson = get(createOrUpdateItemPayload, sectionsFieldPath) as any;

        if (typeof sectionsJson === "undefined") {
          continue; // no sections were provided
        }

        const parameters = entitySelectorFieldAttributes.appearance.parameters;

        for (const section of Array.from(sectionsJson)) {
          const apiKeyJson = get(section, `attributes.${entitySelectorFieldAttributes.api_key}`);

          if (typeof apiKeyJson === "undefined") {
            continue; // no value is present for "categories", "products", ...
          }

          const apiKeyArray = JSON.parse(apiKeyJson);

          if (typeof parameters["minimumEntityCount"] !== "undefined") {
            const minimumEntityCount = parseInt(parameters["minimumEntityCount"] as string);

            if (apiKeyArray.length < minimumEntityCount) {
              ctx.alert(`Minimum entity count is ${minimumEntityCount}`);
              return false;
            }
          }

          if (typeof parameters["maximumEntityCount"] !== "undefined") {
            const maximumEntityCount = parseInt(parameters["maximumEntityCount"] as string);

            if (apiKeyArray.length > maximumEntityCount) {
              ctx.alert(`Maximum entity count is ${maximumEntityCount}`);
              return false;
            }
          }
        }
      }
    }

Hi @kevin.cocquyt,

I just want to make sure I’m understanding correctly here… I think I’m getting a bit confused, sorry?

Is that hook supposed to activate when any block in sections has a field that has another plugin called entitySelector activated?

What is apiKeyJson and why is it an array of API keys instead of a string?

Sorry if I’m misunderstanding this! A few screenshots (or a link to the model/field/plugin in question) would be helpful, please. You can also email that to us at support@datocms.com if you’d rather keep it private.

Thank you!

Thanks for the quick reply. I just sent an e-mail with some extra explanation (text and screenshots).