#Defining a Collection and a Block with the same data?

20 messages · Page 1 of 1 (latest)

flat trout
#

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;
manic sapphire
#

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.

flat trout
#

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?

manic sapphire
#

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

flat trout
#

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

manic sapphire
#

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

flat trout
#

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?


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;```
manic sapphire
#

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

flat trout
#

Cool, thanks for the help.

flat trout
#

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>
  );
};