Like what we’re doing? Star us on GitHub!

Create new menu global after creating a page

Braggedtooth
6 months ago
1 2

Hi!

i am trying to add a page to the global menu after its being created so far i have managed to replace the menu.

This is my current code run in page afterchange hook:

 import payload from "payload";

export const addPageToMenu = async (args) => {
  if (args.operation === "create" {
  
    let menu = await payload.findGlobal({ slug: "mainMenu" });

    if (args.doc) {
      await payload.updateGlobal({
        slug: "mainMenu",
        data: {
          items: [
            {
              type: "link",
              label: args.doc.title,
              link: {
                type: "reference",
                reference: {
                  value: args.doc.id,
                  relationTo: "pages",
                },
              },
              subMenu: { blocks: 0 },
            },
            ...menu.items.map((item) => {
              return {
                link: {
                  ...item.link,
                  reference: {
                    ...item.link.reference,
                    value: {
                      ...item.link.reference.value,
                      layout: {
                        ...item.link.reference.value.layout,
                      },
                    },
                  },
                },
                ...item,
              };
            }),
          ],
        },
      });

      return args.doc;
    }
  }
  return args.doc;
};

this create a new entry but the old entries loses connection is there a way to just use the ids instead of passing the whole referenced document? i.e

{
  "items": [
    {
      "link": {
        "reference": "id of  document"
      }
    }
  ]
}

Error Message:
image

  • Braggedtooth
    6 months ago

    Solution hook for adding page when created and deleting when page is deleted.

    import payload from "payload";
    import { FieldHookArgs } from "payload/dist/fields/config/types";
    import { MainMenu, Page } from "../../payload-types";
    
    /**
     *  fetches the main menu from the database
     */
    const fetchMenu = async (): Promise<MainMenu> =>
      await payload.findGlobal({ slug: "mainMenu" });
    
    /**
     *  fetch the menu, add the new page to it, and then update the menu
     * @param args - {
     * @returns The page that was created.
     */
    export const addPageToMenu = async (args: {
      doc: Page;
      operation: FieldHookArgs["operation"];
    }) => {
      const menu = await fetchMenu();
      if (args.operation === "create") {
        const newArray = menu.items.map((item) => {
          return {
            ...item,
            link: {
              ...item.link,
              reference: {
                value:
                  typeof item.link.reference.value !== "string" &&
                  item.link.reference.value.id,
                relationTo: item.link.reference.relationTo,
              },
            },
          };
        });
        if (args.doc && menu) {
          await payload.updateGlobal({
            slug: "mainMenu",
            data: {
              items: [
                ...newArray,
                {
                  type: "link",
                  label: args.doc.title,
                  link: {
                    type: "reference",
                    reference: {
                      value: args.doc.id,
                      relationTo: "pages",
                    },
                  },
                  subMenu: { blocks: 0 },
                },
              ],
            },
          });
    
          return args.doc;
        }
      }
    };
    /**
     *  fetches the menu, filters out the item with the id that matches the id passed in as an argument,
     * and then updates the menu with the filtered array
     * @param args - { id: string }
     * @returns The return type is a Promise<void>
     */
    
    export const deleteMenu = async (args: { id: string }) => {
      const menu = await fetchMenu();
      const deleteArray = menu.items.filter(
        (element) =>
          typeof element !== "string" &&
          typeof element.link.reference.value !== "string" &&
          element.link.reference.value.id !== args.id
      );
      await payload.updateGlobal({
        slug: "mainMenu",
        data: {
          items: [
            ...deleteArray.map((item) => {
              return {
                ...item,
                link: {
                  ...item.link,
                  reference: {
                    value:
                      typeof item.link.reference.value !== "string" &&
                      item.link.reference.value.id,
                    relationTo: item.link.reference.relationTo,
                  },
                },
              };
            }),
          ],
        },
      });
      return;
    };
  • Braggedtooth
    6 months ago

    Hi!

    I figured it out, the solution is in my question. Just have to pass the id as value instead of the whole object.
    i dont know why i didnt try that first even tho that was how i wanted it to work..
    welp will leave this here. Maybe helps someone else 👍🏿

Open the post
Continue the discussion in GitHub
Can't find what you're looking for?
Get help straight from the Payload team with an Enterprise License.Learn More