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;
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.
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?
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
Haha ok cool, thanks! Isn't the collection defining 1 room at a time? So Room is more relevant?
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
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;
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
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
Discord
online
Get help straight from the Payload team with an Enterprise License.