Lifecycle and components inside collections type

Is it possible to update components that are in collection type every time that collection type is updated? I was thinking to use beforeUpdate lifecycle hook, but it doesn’t have data from components only data from collection type. And if i use extra function and update collection type that way i would trigger infinite loop with lifecycle hook.

Anyone have some idea what to do?

It was possible in v3. There is similar confirmed issue #11980

Hello @Igor_Abramov,

yea i know it was possible in v3, but issue you mention is for adding new repeatable component with api. Im trying to manipulate with existing data inside lifecycle hook.

3 Likes

I am also trying to set a field of an component thats inside of an dynamic zone but i dont see the data.
I only see “id”, “__component”(which is the component type) and “__pivot”.

Hello @WardenCommander, Did you find a solution for this issue?

If yes, can you please share it?

I use 2 collection type

1 Like

Hi guys! Lifecycles still cannot be used in components? I’m trying not to create an extra collection type.

Nope, probably never will, at least not in version 4.

1 Like

Hi @WardenCommander!
I’ve just made a feature request for lifecycle hooks in Components. If you want you can join with a vote!

Feedback Strapi

Thanks!

1 Like

We also just started with migration of our strapi projects.

The fact that data inside of components in dynamic-zones of collection-types are missing in the lifecycle-hooks make strapi useless for us.

Why would you change that behaviour and even consider announcing end of support of v3?

Really disappointed.

2 Likes

hi @luxterful,
Have u found out the solution for this type of issue?

@WaiYan_Kyaw @error_n73

You have to use the component/relation id to query it in it’s specific table.

  • Step 1: Query the component data in your collection’s table:
  • Step 2: Query the current component data in the component’s table, using the id that you have in data itself
  • Step 3: Validate the data as you wish

Example:

lifecycles.js

// get your component data from your collection’s table
const allTerms = await someFile.fetchAllTerms();

// get currentRecord terms from the component's table
const currTerms = await someFile.fetchCurrentTerms(data.terms);

// Validate the data as you wish

someFile.js

// Let's say that the field's name which represents the component  is called: "terms"

// fetch all terms data that are already registered in your collection
async function fetchAllTerms() {
  const records = await strapi.entityService.findMany("your-collection-table-path", {
    populate: ["terms"], // "populate" here is necessary to get the relation data
  });

  const terms = records.map((item) => item.terms);

  return terms;
}

// fetch the lifecycle current component data
// Note: the table that we use here is the components table
async function fetchCurrentTerms(terms) {
  const currTerms = [];
  for (const term of terms) {
    const currTerm = await strapi.entityService.findOne(
      "components.your-component-name",
      term.id, // You use the id from your component that you see inside of data in a lifecycle hook
      {
        fields: ["someFieldName"],
      }
    );
    currTerms.push(currTerm);
  }
  return currTerms;
}

module.exports = {
  fetchAllTerms,
  fetchCurrentTerms,
};

Hope this helps some developers who went through this issue

1 Like

Working solution to add a lifecycle callback directly to component inside of collection.

// src/index.ts
async bootstrap() {

// your code

const _strapi: any = strapi;
    const _metadata: Map<any, any> = _strapi.db.metadata;
    _metadata.set("componentGroup.component", {
      ..._metadata.get("componentGroup.component"),
      lifecycles: {
        beforeUpdate: async (e: Event) => {
          // change data object passed to the lifecycle event
          e.params.data.your_attribute_1 = "new_value";
          // or use current state of component to change data object
          const comp = await strapi
            .query("componentGroup.component")
            .findOne({ where: { id: 25 } });
          e.params.data.your_attribute = comp.your_attribute.concat("new_value");
        },
      },
    });

//your code

}

But then you loose the context of the content type. Typical content type validation should be able to even unpublish a content peace if something can not be validated. Is there really no way in Strapi to validate entities if the data is not on root level?