Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Can Blocks be used without a Layout

default discord avatar
thisisnotchrislast year
53

Hello! I am trying to use a Block on a collection, but not inside of a Layout. The reason is that it's difficult to predict the type of the data on the frontend when iterating over the JSON structure of layout. Can I use Blocks without them being within a Layout field? Thanks!



Example scenario



I have a Global, 'Home Page'. I want to display an Image Banner Block, an About Us Block and a Panels Block.



The type would end up being something like this for the DTO



interface HomePage {
  layout: (Banner | AboutSection | { panels: Panel[] })[];
  globalType: string;
  createdAt: string;
  updatedAt: string;
  id: string;
}


But that's not the easiest to iterate over as the Blocks do not share the same structure



I feel like it would almost be better to have layout mapped out by key (id of the block instance?)



interface HomePage {
  layout: {
    homePageBanner: Banner
    homePagePanels: Panels[]
    homePageAboutSection: AboutSection
   }


That way when you go to use the data, you can specify

layout.homePageBanner

, and the type is already available



@jmikrut Doesn't this seem like a cleaner approach to the layout object?



Currently, here is my unfinished mapping of this data on my frontend. Not super pleasant to work with:



    this.cms.getHomePage().subscribe({
      next: (data) => {
        // This is bad use of TS, fix.
        this.panels = (
          data.layout.filter(
            (block: any) => block.blockType === 'Panels'
          )[0] as any
        ).panels;

        this.banner = data.layout.filter(
          (block: any) => block.blockType === 'Banner'
        )[0];

        this.cta = data.layout.filter(
          (block: any) => block.blockType === 'CallToAction'
        )[0];
        console.log(data.layout);
      },
      error: (error: HttpErrorResponse) => {
        if (error.status === 404 || error.status === 500) {
          console.error('Unable to reach Payload API');
        } else {
          console.error(error);
        }
      },
    });


(Ignore lack of length check, etc)



@noheadphones What are your thoughts on this? Am I doing something completely wrong with this approach?



(apart from using Observables lol)



The only other clean option I can imagine is explicitly listing the structure of Layout in the order currently in the CMS



OR



Perhaps I need to use multiple layouts



One per block



But I imagine Layout would still be an array

  • default discord avatar
    Tinoutilast year

    If the layout of that page is known and fixed, do you even need to use

    blocks

    here? Wouldn't it make more sense to just make

    groups

    in that case? 🤔

  • default discord avatar
    thisisnotchrislast year

    doh' you're right, that would be better

  • discord user avatar
    jmikrut
    last year

    yea that was my thought but then i got distracted



    haha

  • default discord avatar
    thisisnotchrislast year

    Wait



    @jmikrut Same issue I think



    Not going to copy all the json but



    using groups, the structure was generated as follows



    const HomePage: GlobalConfig = {
      slug: "homePage",
      access: {
        read: () => true,
        update: isCmsAdmin,
      },
      fields: [
        {
          name: "mainbanner",
          label: "Main Banner",
          type: "group",
          fields: [
            {
              name: "bannerTitle",
              label: "Image Banner Title",
              type: "text",
              required: true,
            },
            {
              name: "bannerSubTitle",
              label: "Image Banner SubTitle",
              type: "text",
              required: true,
            },
            {
              name: "image",
              type: "upload",
              relationTo: "media",
              required: true,
            },
          ],
        },


    I think I was expecting something like



    fields: {
      mainbanner: {}
    }


    because the whole idea was to make it so I didn't have to iterate over fields and check the type

  • default discord avatar
    Tinoutilast year

    is this not what you're getting out of the API?

  • default discord avatar
    thisisnotchrislast year

    From the API, I have my main fields array



    But I guess I was expecting the groups to be available via key rather than iterating over nested fields



    But that may not be possible

  • default discord avatar
    Tinoutilast year

    That was I assumed it would return as well, is that not the case? Like in your example,

    data.mainBanner.bannerTitle

    ? 🤔

  • default discord avatar
    thisisnotchrislast year

    nope, it is



          name: "mainbanner",
          label: "Main Banner",
          type: "group",
          fields: [
            {
              name: "bannerTitle",
              label: "Image Banner Title",
              type: "text",
              required: true,
            },


    So I'm thinking filtering is non avoidable

  • default discord avatar
    Tinoutilast year

    That's your config though, what does the data look like? 👀


    I think I might be misunderstanding what you're trying to do. 😄


    Is what you're trying to do not on the front end side?

  • default discord avatar
    Tinoutilast year
    That's using groups, right?
  • default discord avatar
    thisisnotchrislast year

    im just a moron



    yeahhhhhhh

  • default discord avatar
    Tinoutilast year

    Sorry,

    blocks

    *

  • default discord avatar
    thisisnotchrislast year

    I had changed the structure and mongo recorded that



    so the json output is dirty



    let me make a new global

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team..