How to linked/upload nested and main sub component

System Information
  • Strapi Version: 4.11.5
  • Operating System: win/mac
  • Database: postgres
  • Node Version: v16.10.0
  • NPM Version: 7.24.0
  • Yarn Version: 1.22.19

In the attached screenshot, I have a nested content-type builder component that is linked to my main content type. However, when attempting to upload files using Strapi’s default plugin API controller, while the content details are appropriately updated and the files are successfully added to the media library, the expected linkage between these uploaded files and their corresponding entries in the content type is not being established. This issue seems to stem from the lack of association between the media library files and the specific content entries within the content type configuration. any suggestion will be greatly appreciated…! thank you😄.

Currently working on the same problem, but just managed to have some sort of solution: What you have to do in the custom controller that manages your upload endpoint is this:
await strapi.plugins.upload.services.upload.upload({
data: {
},
ref: “api::xxxxx.xxxx”,
refId: 11,
field: “fichier”,
},
files: {
…ctx.request.files.files,
},
});

with ref, refId, and field being the relevant data to do the linking

Just setting the field name ignoring the name of the component it’s inside don’t work here.

Like: if i have a component called “documents” that have “doc_front” image field,

and i just use “doc_front” as the “ref” property

just dont work here.

also, trying the ref property with “documents.doc_front” don’t work…

the image uploads and server return success, but there is no relation with the image and the field i want to.

i think there isn’t any way to make it work. D= really sad

1 Like

For anyone trying to do this and searching for workarounds …

You can’t use the Upload service or API route to upload a file and relate it with a field OF A COMPONENT.

If you need to upload and relate with a field of a component, a workaround is to create a custom route that first upload de image without any relation and then update the entry and the field you want to relate with the image.

In my case, i have the component “documents” that have two field of type media (the names are rg_front and rg_back). I’m using this component in my User collection (user-permissions).

So, i created a custom controller for the collection User called updateDocument, that receive a file and a name of the component it should related with inside the “documents” component.

I know it’s really specific, but i’m sure you can use the same logic and create custom controllers for want you need to update.

plugin.controllers.user.updateDocument = async (ctx) => {
    if (!ctx.state.user || !ctx.state.user.id) {
      return (ctx.response.status = 401);
    }

    const body = { ...ctx.request.body };
    const acceptedNames = ["rg_front", "rg_back"];
    const isDocNameAuthorized =
      body.docName && acceptedNames.includes(body.docName);

    if (!isDocNameAuthorized) {
      return (ctx.response.status = 400);
    }

    try {
      const { files } = ctx.request.files;
      const data = {};

      if (files) {
        const uploadedFile = await strapi
          .service("plugin::upload.upload")
          .upload({
            data,
            files,
          });

        await strapi.entityService.update(
          "plugin::users-permissions.user",
          ctx.state.user.id,
          {
            data: {
              documents: {
                [body.docName]: uploadedFile[0].id,
              },
            },
          }
        );

        return uploadedFile;
      } else {
        return ctx.send({ error: "There is no file uploaded" }, 400);
      }
    } catch (error) {
      console.error(error);
      return ctx.send({ error: "Error uploading files" }, 500);
    }
  };

  plugin.routes["content-api"].routes.push({
    method: "PUT",
    path: "/user/updateDocument",
    handler: "user.updateDocument",
    config: {
      prefix: "",
    },
  });

Be aware to use strapi.entityService.update() instead of strapi.query().update, because the second one don’t update component fields, at least in this case.

1 Like