หน้า landing page จาก blocks
สิ่งที่จะได้
collection pages ที่เนื้อหาเป็นรายการ block (ส่วนหัว จุดเด่น ปุ่มชวนคลิก) ให้ผู้แก้เพิ่ม เรียงใหม่ และกรอกเอง พร้อมหน้าเว็บที่แสดงผล ใช้: blocks
1. Collection
ts
{
slug: 'pages',
useAsTitle: 'title',
drafts: true,
preview: ({ doc }) => `/${doc.slug ?? ''}`,
access: { read: ({ user }) => (user ? true : { status: { equals: 'published' } }) },
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'slug', type: 'slug', from: 'title' },
{
name: 'layout',
type: 'blocks',
blocks: [
{
slug: 'hero',
labels: { singular: { en: 'Hero', th: 'ส่วนหัว' } },
fields: [
{ name: 'heading', type: 'text', required: true },
{ name: 'text', type: 'textarea' },
{ name: 'image', type: 'upload' },
],
},
{
slug: 'features',
labels: { singular: { en: 'Features', th: 'จุดเด่น' } },
fields: [
{
name: 'items',
type: 'array',
maxRows: 6,
fields: [
{ name: 'title', type: 'text', required: true },
{ name: 'text', type: 'textarea' },
],
},
],
},
{
slug: 'cta',
labels: { singular: { en: 'Call to action', th: 'ปุ่มชวนคลิก' } },
fields: [
{ name: 'text', type: 'text', required: true },
{ name: 'buttonLabel', type: 'text', required: true },
{ name: 'buttonUrl', type: 'text', required: true },
],
},
],
},
],
}ในหน้า admin ปุ่ม เพิ่มบล็อก มีให้เลือกสามแบบ และลากแถวเพื่อเรียงลำดับได้
2. แสดงผล
แยกตาม blockType TypeScript จะจำกัด type ของแต่ละแถวให้ตรงกับ field ของ block นั้น
vue
<template>
<template v-for="block in page.layout" :key="block.id">
<section v-if="block.blockType === 'hero'" class="hero">
<h1>{{ block.heading }}</h1>
<p>{{ block.text }}</p>
</section>
<section v-else-if="block.blockType === 'features'" class="features">
<div v-for="item in block.items" :key="item.id">
<h3>{{ item.title }}</h3>
<p>{{ item.text }}</p>
</div>
</section>
<section v-else-if="block.blockType === 'cta'" class="cta">
<p>{{ block.text }}</p>
<a :href="block.buttonUrl">{{ block.buttonLabel }}</a>
</section>
</template>
</template>tsx
export function Blocks({ layout }: { layout: Page['layout'] }) {
return layout?.map((block) => {
switch (block.blockType) {
case 'hero':
return <section key={block.id}><h1>{block.heading}</h1><p>{block.text}</p></section>
case 'features':
return (
<section key={block.id}>
{block.items?.map((item) => <div key={item.id}><h3>{item.title}</h3><p>{item.text}</p></div>)}
</section>
)
case 'cta':
return <section key={block.id}><p>{block.text}</p><a href={block.buttonUrl}>{block.buttonLabel}</a></section>
}
})
}Page คือ CollectionDocument<typeof config, 'pages'> ดู TypeScript
3. ค้นหาข้างใน blocks
ts
// หน้าที่มีปุ่มชวนคลิก
await cms.find('pages', { where: { 'layout.blockType': { equals: 'cta' } } })