How to linked/upload nested and main sub component

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