Defining a Collection and a Block with the same data?

default discord avatar
Taunlast year
20

Hi. I'm confused about a process between defining a collection called Room (hotel rooms) and rendering those rooms within a block component. Ideally the admin selects the rooms to be featured (3 rooms that will be displayed next to each other) and the block component renders the title, description, featured image, images, price to that the page.



Once I define the collection config and upload the rooms data, do I still need to create all of those room fields for the block config or can I fetch the data by importing the Room fields?



What approach do you suggest? I'm using Nextjs PayloadCMS custom-server template (mono-repo).



Room.ts


import { CollectionConfig } from 'payload/types';

const Room: CollectionConfig = {
    slug: 'room',
    access: {
      read: (): boolean => true, // Everyone can read Rooms
    },
    fields: [
      {
        name: 'title',
        label: 'Title',
        type: 'text',
        required: true,
      },
      {
        name: 'featuredImage',
        label: 'Featured Image',
        type: 'upload',
        relationTo: 'media',
        required: true,
      },
      {
        name: 'images',
        label: 'Images',
        type: 'array',
        minRows: 1,
        fields: [
          {
            name: 'image',
            label: 'Image',
            type: 'upload',
            relationTo: 'media',
            required: true,
          },
        ],
        required: true,
      },
      {
        name: 'description',
        label: 'Description',
        type: 'richText',
        required: true,
      },
      {
        name: 'price',
        label: 'Price',
        type: 'number',
        required: true,
      },
    ],
  };
  
  export default Room;
  • default discord avatar
    Marťafiixeklast year

    You would create a new block called for example

    RoomsBlock

    which would contain a field similar to this:


    fields: [
      {
        name: "selectRooms", // Name of the field inside the block
        type: "relationship",
        relationTo: "rooms", // Points a relation to your rooms collection
        hasMany: true, // Enables selecting multiple rooms
      },
    ],

    Inside Payload CMS you would select which rooms you want to show on the website.



    In Next.js code you would render the appropriate component. The component is going to take in

    selectRooms

    as props, therefore you can render the rooms as you need.

  • default discord avatar
    Taunlast year

    Great, thank you.



    So the RoomsBlock.ts config can look like this?



    const RoomsBlock = {
      slug: 'rooms-block',
      labels: {
        singular: 'Rooms Block',
        plural: 'Rooms Blocks',
      },
      fields: [
        {
          name: 'selectRooms',
          type: 'relationship',
          relationTo: 'rooms',
          hasMany: true,
        },
      ],
    };
    
    module.exports = {
      collections: [Room],
      blocks: [RoomsBlock],
    };


    ChatGPT recommended

    module.exports = {
      collections: [Room],
      blocks: [RoomsBlock],
    };

    instead of default export. Should I default export?

  • default discord avatar
    Marťafiixeklast year

    What ChatGPT recommended is wrong. You should have collection

    rooms

    as

    collections/Rooms.ts

    , block should be as

    blocks/RoomsBlock.ts

    .



    Therefore

    collections/Rooms.ts

    has it's own

    export default Room

    and block should have

    export default RoomsBlock


    I would also suggest to not depend ChatGPT as it's abilities have gone rapidly downhill 😄



    And also it's unusable with Payload because ChatGPT doesn't have enough data about Payload CMS



    And bear in mind that inside

    payload.config.ts

    you only have to import collections or globals



    Blocks are imported inside collections where you want to use them

  • default discord avatar
    Taunlast year

    Haha ok cool, thanks! Isn't the collection defining 1 room at a time? So Room is more relevant?

  • default discord avatar
    Marťafiixeklast year

    It's a collection = collection consists of multiple rooms



    Also it's a sort of standard, I think Payload team uses plurals too in their examples or their official website CMS

  • default discord avatar
    Taunlast year

    Cool, thanks. Is it standard convention to name the block with 'Block' in it's title. eg. RoomsBlock.tsx ?



    Therefore collections/Rooms.ts has it's own export default Room and block should have export default RoomsBlock


    "



    To clarify - the Rooms.ts collection should export as singular 'Room'?



    Is this correct?



     import { CollectionConfig } from 'payload/types';
    
    const Room: CollectionConfig = {
        slug: 'rooms',
        access: {
          read: (): boolean => true, // Everyone can read Rooms
        },
        fields: [
          {
            name: 'title',
            label: 'Title',
            type: 'text',
            required: true,
          },
          {
            name: 'featuredImage',
            label: 'Featured Image',
            type: 'upload',
            relationTo: 'media',
            required: true,
          },
          {
            name: 'images',
            label: 'Images',
            type: 'array',
            minRows: 1,
            fields: [
              {
                name: 'image',
                label: 'Image',
                type: 'upload',
                relationTo: 'media',
                required: true,
              },
            ],
            required: true,
          },
          {
            name: 'description',
            label: 'Description',
            type: 'richText',
            required: true,
          },
          {
            name: 'price',
            label: 'Price',
            type: 'number',
            required: true,
          },
        ],
      };
      
      export default Room;
  • default discord avatar
    Marťafiixeklast year

    I mean, you can name the

    constant

    how you want, but you should keep the

    slug

    in plural form



    Therefore yes, the above is correct



    And you can save the collection as

    Room.ts

    or

    Rooms.ts


    That choice is yours

  • default discord avatar
    Taunlast year

    Cool, thanks for the help.



    I'm lost. I've got a Config.ts within a Rooms folder that provides the fields for the admin to select the rooms that were saved to the Room collection.


    I'd like the RoomsBlock to render the selected rooms. Right now I'm just trying to render the data, I'll style it later. What should my Component.ts code be?



     
    import React from 'react';
    import { Block } from 'payload/types';
    
    export const Rooms: Block = {
      slug: 'rooms-block',
      labels: {
        singular: 'Rooms Block',
        plural: 'Rooms Blocks',
      },
      fields: [
      {
          name: 'selectRooms',
          type: 'relationship',
          relationTo: 'rooms',
          hasMany: true,
        },
      ],
    };


    Component.ts


    import React from 'react';
    import NextImage from 'next/image';
    import RichText from '../../components/RichText';
    import classes from './index.module.css';
    import sizes from './sizes.json';
    import { MediaType } from '../../collections/Media';
    import { Rooms } from './Config';
    
    
    export type RoomsBlockProps = {
        selectRooms: Array<any>;
      };
    
    export const RoomsBlock: React.FC<RoomsBlockProps> = ({ selectRooms }) => {
      return (
        <div>
          {selectRooms.map((room) => (
            <div key={room._id}>
              <h2>{room.title}</h2>
              <img src={room.featuredImage.url} alt={room.featuredImage.alt} />
              <p>{room.description}</p>
              <p>Price: {room.price}</p>
            </div>
          ))}
        </div>
      );
    };


    collection / Room.ts


     import { CollectionConfig } from 'payload/types';
    
    const Room: CollectionConfig = {
        slug: 'rooms',
        fields: [
            {
                name: 'title',
                label: 'Room Title',
                type: 'text',
                required: true,
            },
    {
        name: 'featuredImage',
        label: 'Featured Image',
        type: 'upload',
        relationTo: 'media',
        required: true,
      },
      {
        name: 'images',
        label: 'Images',
        type: 'array',
        minRows: 1,
        fields: [
          {
            name: 'image',
            label: 'Image',
            type: 'upload',
            relationTo: 'media',
            required: true,
          },
        ],
      },
      {
        name: 'description',
        label: 'Description',
        type: 'richText',
        required: true,
      },
      {
        name: 'price',
        label: 'Price',
        type: 'number',
        required: true,
      },
    ],
    };
    
    export default Room;
Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get help straight from the Payload team with an Enterprise License.