Skip to main content

[Thủ Thuật WP] Hướng dẫn tạo Gutenberg Block trong WordPress

Bài viết hướng dẫn tạo một Gutenberg Block Plugin có tên là Affiliate Block. Block này gồm 2 cột một bên là hình ảnh bên trái và một đoạn text bên phải, và thêm một button tùy chỉnh link liên kết bên dưới text.

Image
Hướng dẫn tạo Gutenberg Block trong Wordpress

Bắt đầu thôi!

Bước 1: Tạo một Gutenberg Block Plugin

 Đầu tiên vào thư mục /wp-content/plugins và chạy lệnh

npx @wordpress/create-block my-affiliate-block

Lệnh trên sẽ chạy và tạo ra một thư mục plugin my-affiliate-block.

Để hiểu hơn cách hoạt động của lệnh command trên có thể xem thêm : Tạo Custom Block Gutenberg trong WordPress

Sau khi cài đặt xong để chạy được plugin bạn lần lượt thực hiện như sau: 

+ Chạy lệnh cd đển thư mục plugin này

cd my-affiliate-block

+ Khởi động môi trường devlopment bằng lệnh

npm start

+ Vào nơi quản lý Plugin trong WordPress và active nó

Image
Tạo block plugin - active plugin

+ Sau khi active block plugin, bạn hãy đến tạo mới một post và mở block inserter và kéo xuống để thấy được block "Affiliate Block" như hình 

Image
Hướng dẫn tạo Gutenberg Block trong Wordpress - Affiliate Block

Bước 2 : Khám phá cấu trúc của Gutenberg Block Plugin

Image
Cấu trúc Gutenberg Block Plugin trong Wordpress

2.1. File my-affiliate-block.php - Khai báo một block type 

Để khai báo Block Type bằng hàm register_block_type để nhận lấy metadata về block trong file block.json.

<?php
/**
 * Plugin Name:       My Affiliate Block
 * Description:       Example block written with ESNext standard and JSX support – build step required.
 * Requires at least: 5.8
 * Requires PHP:      7.0
 * Version:           0.1.0
 * Author:            The WordPress Contributors
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       my-affiliate-block
 *
 * @package           create-block
 */

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
function create_block_my_affiliate_block_block_init() {
	register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'create_block_my_affiliate_block_block_init' );

2.2. File package.json - Nơi lưu thông tin dependency của projects và lệnh script

devDependencies @wordpress/scripts là mặc định, nếu bạn cần thêm các packages thì đây sẽ là nơi lưu giữ thông tin đó.

Trong phạm vi bài viết chỉ dùng 2 lệnh script cơ bản:

  • npm run build — tạo file build cho project
  • npm run start — tạo file development cho project

2.3. File block.json  - Nơi lưu thông tin của Gutenberg Block Plugin

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "create-block/my-affiliate-block",
	"version": "0.1.0",
	"title": "My Affiliate Block",
	"category": "widgets",
	"icon": "smiley",
	"description": "Example block written with ESNext standard and JSX support – build step required.",
	"supports": {
		"html": false
	},
	"textdomain": "my-affiliate-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}
  • apiVersion — phiên bản API được block sử dụng (phiên bản hiện tại là 2)
  • name — một tên định danh duy nhất cho một block
  • version — phiên bản hiện tại của block
  • title — một tiêu đề hiển thị cho block
  • category — a block category
  • icon — là biểu tượng của block, xem thêm tại Dashicon. ( Có thể custom một icon svg)
  • description — mô tả về block
  • supports — là option để kiểm soát tính năng trong editor
  • editorScript — đường đẫn file script 
  • editorStyle — đường đẫn file style
  • style — cung cấp các style khác cho block

2.4. Folder src  - Nơi chứa code của Gutenberg Block Plugin

Gồm lần lượt các file:

index.js : sẽ là file bắt đầu, nơi bạn import các dependencies và đăng ký block type.

edit.js: là nơi bạn xây dựng giao diện cho block trong editor.

save.js: nơi bạn xử lý dữ liệu khi save block vào database.

editor.scss: là nơi chứa style cho block trong editor.

+ style.scss: là nơi chưa style cho block ở front-end, giao diện người dùng.

2.5. Folder node_modules  - Nơi chứa các packages bạn khai báo trong package.json

2.6. Folder build sử dụng khi bạn dùng lệnh build cho block plugin

Bước 3 : Thêm tham số cho block.json

Ta thay đổi nội dung block.json như sau

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "create-block/my-affiliate-block",
	"version": "0.1.0",
	"title": "My Affiliate Block",
	"category": "widgets",
	"icon": "money",
	"keywords": [ "kinsta", "affiliate", "money" ],
	"description": "Example block written with ESNext standard and JSX support – build step required.",
	"supports": {
		"html": false
	},
	"textdomain": "my-affiliate-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

Trong đó, ta thay đổi icon money.

keywords là array chứa các từ khóa mà khi nhập vào input sẽ xuất hiện block này, điều này giúp ta nhanh tìm ra block của mình trong Block Inserter.

Image
tìm kiếm block nhanh bằng keywords

Bước 4 : Cài đặt thêm các packages 

Sử dụng lệnh command npm install @wordpress/i18n để lần lượt cài đặt các packages khác @wordpress/block-editor@wordpress/blocks. Lúc này file package.json sẽ như thế này:

{
	"name": "my-affiliate-block",
	"version": "0.1.0",
	"description": "Example block written with ESNext standard and JSX support – build step required.",
	"author": "The WordPress Contributors",
	"license": "GPL-2.0-or-later",
	"main": "build/index.js",
	"scripts": {
		"build": "wp-scripts build",
		"format": "wp-scripts format",
		"lint:css": "wp-scripts lint-style",
		"lint:js": "wp-scripts lint-js",
		"packages-update": "wp-scripts packages-update",
		"plugin-zip": "wp-scripts plugin-zip",
		"start": "wp-scripts start"
	},
	"devDependencies": {
		"@wordpress/scripts": "^22.1.0"
	},
	"dependencies": {
		"@wordpress/block-editor": "^8.2.0",
		"@wordpress/blocks": "^11.2.2",
		"@wordpress/i18n": "^4.3.1"
	}
}

Bước 5: Import các components từ packages

5.1. Mở file edit.js thay đổi import useBlockProps và RichText 

import { useBlockProps } from '@wordpress/block-editor';
// Thay thành
import { useBlockProps, RichText } from '@wordpress/block-editor';

Chú ý nếu xóa useBlockProps block của bạn sẽ không được truy cập vào function và style mà chỉ hiển thị text đơn thuần.

RichText component cho phép bạn chỉnh sử và định dạnh nội dung của block. Bạn xem thêm tại đây RichText Component.

5.2. Thay đổi return block bằng component RichText

export default function Edit() {
	const blockProps = useBlockProps();

	return (
		<RichText 
			{ ...blockProps }
			tagName="p"
			onChange={ onChangeContent }
			allowedFormats={ [ 'core/bold', 'core/italic' ] }
			value={ attributes.content }
			placeholder={ __( 'Write your text...' ) }
		/>
	);
}

tagName - tên thẻ của phần tử HTML có thể chỉnh sửa

onChange - function được gọi khi nội dung của phần tử thay đổi

allowFormats - một mảng các định dạng được phép. Theo mặc định, tất cả các định dạng đều được phép

value  - chuỗi HTML để có thể chỉnh sửa

5.3 Xác định các thuộc tính cần thiết trong file block.json

Các thuộc tính cung cấp thông tin về dữ liệu lưu trữ của block, chẳng hạn như nội dung, màu nền, URL, v.v.

Bạn có thể để một số thuộc tính tùy ý trong  object bằng các cặp key/value, trong đó key là tên thuộc tính và value là định nghĩa thuộc tính.

Bây giờ, hãy mở tệp block.json và thêm các thuộc tính prop sau:

"attributes": {
	"content": {
		"type": "string",
		"source": "html",
		"selector": "p"
	}
},

Thuộc tính content cho phép lưu trữ văn bản do người dùng nhập vào trường có thể chỉnh sửa:

  • Type cho biết loại dữ liệu được lưu trữ bởi thuộc tính. Kiểu này là bắt buộc trừ khi bạn xác định thuộc tính là enum.
  • source định nghĩa cách giá trị thuộc tính được trích lấy từ ​​nội dung bài đăng. Trong ví dụ này, đó là nội dung HTML. Lưu ý rằng nếu bạn không cung cấp thuộc tính source, dữ liệu sẽ được lưu trữ trong dấu phân cách khối (đọc thêm).
  • selector là thẻ HTML hoặc bất kỳ selector khác, chẳng hạn như class hoặc thuộc tính id.

Chúng ta sẽ chuyển cho function Edit một object của các thuộc tính. Vì vậy, hãy quay lại file edit.js và thực hiện thay đổi sau:

export default function Edit( { attributes, setAttributes } ) { ... }

5.4. Khai báo event Handlers - hàm xử lý sự kiện

Phần tử RichText có thuộc tính onChange, cung cấp một hàm để gọi khi nội dung của phần tử thay đổi.

Hãy xác định chức năng đó và xem toàn bộ file edit.js:

import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();

	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}

	return (
		<RichText 
			{ ...blockProps }
			tagName="p"
			onChange={ onChangeContent }
			allowedFormats={ [ 'core/bold', 'core/italic' ] }
			value={ attributes.content }
			placeholder={ __( 'Write your text...' ) }
		/>
	);
}

Bây giờ hãy lưu file và chạy npm run start trong terminal . Sau đó, quay lại bảng điều khiển WordPress của bạn, tạo một bài đăng hoặc trang mới và thêm Affiliate block:

Image
Kết quả tạo custom block

Thêm một số text và chuyển sang Chế độ xem code . Đây là mã của bạn sẽ trông như thế này:

<!-- wp:my-affiliate-plugin/my-affiliate-block -->
<p class="wp-block-my-affiliate-plugin-my-affiliate-block">This is my first editable Gutenberg block ?</p>
<!-- /wp:my-affiliate-plugin/my-affiliate-block -->

Nếu bây giờ bạn lưu trang và kiểm tra kết quả từ giao diện người dùng, bạn có thể hơi thất vọng vì những thay đổi của bạn không ảnh hưởng đến trang web.

Đó là vì bạn phải sửa đổi file save.js để lưu trữ thông tin nhập của người dùng trong cơ sở dữ liệu khi bài đăng được lưu.

5.5. Lưu dữ liệu block

Bây giờ mở file save.js và thay đổi scripts như bên dưới

import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ attributes.content } 
		/>
	);
}

Giải thích cho đoạn code ở đây:

  • Import component RichText từ block-editor.
  • Chuyển một số thuộc tính thông qua một đối số object vào hàm lưu (trong ví dụ này, chúng tôi chỉ truyền thuộc tính thuộc tính attributes )
  • Trả lại nội dung của component RichText 

Bước 6: Thêm Block Toolbar cho Gutenberg Block Plugin

Block toolbar là nơi chứa một tập hợp các điều khiển cho phép người dùng thao tác các phần của nội dung block. Đối với mỗi điều khiển thanh công cụ, bạn sẽ tìm thấy một component:

Image
Block Toolbar

6.1. Import BlockControls và  AlignmentControl 

Mở file edit.js và thêm :

import { 
	useBlockProps, 
	RichText, 
	AlignmentControl, 
	BlockControls 
} from '@wordpress/block-editor';

6.2. Thêm component  BlockControls và  AlignmentControl vào return

Trong cùng cấp bậc với RichText, ta thêm vào trong file edit.js như sau:

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();
	return (
		<>
			<BlockControls>
				<AlignmentControl
					value={ attributes.align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ attributes.content }
				placeholder={ __( 'Write your text...' ) }
				style={ { textAlign: attributes.align } }
			/>
		</>
	);
}

Trong đó <> và </> là cú pháp khai báo các đoạn React, giúp ta trả về nhiều phần tử trong React.

Trong ví dụ này, AlignmentControl có hai thuộc tính:

  • Value cung cấp giá trị hiện tại cho phần tử
  • onChange cung cấp một hàm xử lý sự kiện để chạy khi giá trị thay đổi

Chúng ta cũng đã xác định các thuộc tính bổ sung cho phần tử RichText.

6.3. Thêm thuộc tính align cho Block

Mở file block.js và thêm thuộc tính align 

"align": {
	"type": "string",
	"default": "none"
}

Quay trở về terminal để chạy lệnh npm run start

Image
alignment-block-toolbar

Nhưng để sử dụng căn chỉnh Align thì cần phải thêm hàm xử lý event.

6.4. Thêm Event Handler cho align của Block

const onChangeAlign = ( newAlign ) => {
	setAttributes( { 
		align: newAlign === undefined ? 'none' : newAlign, 
	} )
}

và khi đó file edit.js sẽ trông như thế này

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();
	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}
	return (
		<>
			<BlockControls>
				<AlignmentControl
					value={ attributes.align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ attributes.content }
				placeholder={ __( 'Write your text...' ) }
				style={ { textAlign: attributes.align } }
			/>
		</>
	);
}

6.5. Xử lý lưu trữ dữ liệu

Mở file save.js và thay đoạn bên dưới

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	const { content, align } = attributes;
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ content } 
			style={ { textAlign: align } }
		/>
	);
}

Như vậy là chúng ta đã tạo thành công block toolbar cho block của mình.

Bước 7: Tạo Block Setting Sidebar cho Gutenberg Block Plugin

Bạn có thể tạo một block setting sidebar hoặc tạo một sidebar mới thông qua API InspectorControls.

Tương tự như bước 5,6. Bước 7 sẽ đi nhanh qua như sau.

7.1.  Import InspectorControls và PanelColorSettings Components

Mở file edit.js và import thêm các components

import { 
	useBlockProps, 
	RichText, 
	AlignmentControl, 
	BlockControls,
	InspectorControls,
	PanelColorSettings
} from '@wordpress/block-editor';

7.2.  Thay đổi return của edit.js với component mới

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();
	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}
	return (
		<>
			<InspectorControls>
				<PanelColorSettings 
					title={ __( 'Color settings', 'my-affiliate-block' ) }
					initialOpen={ false }
					colorSettings={ [
						{
						  value: textColor,
						  onChange: onChangeTextColor,
						  label: __( 'Text color', 'my-affiliate-block' ),
						},
						{
						  value: backgroundColor,
						  onChange: onChangeBackgroundColor,
						  label: __( 'Background color', 'my-affiliate-block' ),
						}
					] }
				/>
			</InspectorControls>
			<BlockControls>
				<AlignmentControl
					value={ attributes.align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ attributes.content }
				placeholder={ __( 'Write your text...', 'my-affiliate-block' ) }
				style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
			/>
		</>
	);
}

Chú ý đã có sự thay đổi với component RichText với sự thuộc tính style.

7.3. Thêm Attributes vào block.json

"attributes": {
	"content": {
		"type": "string",
		"source": "html",
		"selector": "p"
	},
	"align": {
		"type": "string",
		"default": "none"
	},
	"backgroundColor": {
		"type": "string"
	},	 
	"textColor": {
		"type": "string"
	}
},

7.4. Xử lý xự kiện bằng cách thêm vào file edit.js

const onChangeBackgroundColor = ( newBackgroundColor ) => {
	setAttributes( { backgroundColor: newBackgroundColor } )
}
const onChangeTextColor = ( newTextColor ) => {
	setAttributes( { textColor: newTextColor } )
}

7.5. Xử lý dữ liệu lưu trữ

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	const { content, align, backgroundColor, textColor } = attributes;
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ content } 
			style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
		/>
	);
}

Quay lại chạy lện npm run start

Image
Tạo Block setting sidebar

Bước 8: Tạo External Link cho button

8.1. Import components từ @wordpress/components vào edit.js

import {
	TextControl,
	PanelBody,
	PanelRow,
	ToggleControl,
	ExternalLink
} from '@wordpress/components';
  • PanelBody thêm một vùng chứa có thể thu gọn vào thanh cài đặt. bên cạnh
  • PaneRow tạo một vùng chứa chung cho các điều khiển thanh bên.
  • TextControl cung cấp một điều khiển nhập text input.
  • ToggleControl cung cấp một nút chuyển đổi cho phép người dùng lựa chọn bật / tắt
  • ExternalLink là một thành phần đơn giản để thêm một liên kết bên ngoài.

8.2. Return element ExternalLink  vào edit.js

Đặt cùng cấp với element RichText

<div { ...blockProps }>
	<RichText 
		...
	/>
	<ExternalLink 
		href={ affiliateLink }
		className="affiliate-button"
		rel={ hasLinkNofollow ? "nofollow" : "" }
	>
			{ linkLabel }
	</ExternalLink>

</div>

Sau đó thêm setting vào block sidebar bằng element PanelBody trong InspectorControls 

<InspectorControls>
	<PanelColorSettings 
	...
	/>
	<PanelBody 
		title={ __( 'Link Settings', 'my-affiliate-block' )}
		initialOpen={true}
	>
	...
	</PanelBody>
</InspectorControls>

Tiếp theo chúng ta thêm 2 PanelRow trong PanelBody giúp người dùng có thể cài đặt label và url 

<PanelBody 
	title={ __( 'Link Settings', 'my-affiliate-block' )}
	initialOpen={true}
>
	<PanelRow>
		<fieldset>
			<TextControl
				label={__( 'Affiliate link', 'my-affiliate-block' )}
				value={ affiliateLink }
				onChange={ onChangeAffiliateLink }
				help={ __( 'Add your affiliate link', 'my-affiliate-block' )}
			/>
		</fieldset>
	</PanelRow>
	<PanelRow>
		<fieldset>
			<TextControl
				label={__( 'Link label', 'my-affiliate-block' )}
				value={ linkLabel }
				onChange={ onChangeLinkLabel }
				help={ __( 'Add link label', 'my-affiliate-block' )}
			/>
		</fieldset>
	</PanelRow>
</PanelBody>

Bây giờ chúng ta thêm một điều kiện xuất hiện bằng ToggleControl để người dùng tắt/ bật 

<PanelRow>
	<fieldset>
		<ToggleControl
			label="Add rel = nofollow"
			help={
				hasLinkNofollow
					? 'Has rel nofollow.'
					: 'No rel nofollow.'
			}
			checked={ hasLinkNofollow }
			onChange={ toggleNofollow }
		/>
	</fieldset>
</PanelRow>

8.3. Thêm thuộc tính cho block.json

"affiliateLink": {
	"type": "string",
	"default": ""
},
"linkLabel": {
	"type": "string",
	"default": "Check it out!"
},
"hasLinkNofollow": {
	"type": "boolean",
	"default": false
}

8.4. Thêm hàm xử lý sự kiện vào edit.js

const onChangeAffiliateLink = ( newAffiliateLink ) => {
	setAttributes( { affiliateLink: newAffiliateLink === undefined ? '' : newAffiliateLink } )
}

const onChangeLinkLabel = ( newLinkLabel ) => {
	setAttributes( { linkLabel: newLinkLabel === undefined ? '' : newLinkLabel } )
}

const toggleNofollow = () => {
	setAttributes( { hasLinkNofollow: ! hasLinkNofollow } )
}

8.5. Lưu dữ liệu ở file save.js

export default function save( { attributes } ) {

	const { align, content, backgroundColor, textColor, affiliateLink, linkLabel, hasLinkNofollow } = attributes;

	const blockProps = useBlockProps.save();

	return (
		<div { ...blockProps }>
			<RichText.Content 
				tagName="p" 
				value={ content } 
				style={ { backgroundColor: backgroundColor, color: textColor } }
			/>
			<p>
				<a 
					href={ affiliateLink }
					className="affiliate-button"
					rel={ hasLinkNofollow ? "nofollow" : "noopener noreferrer" }
				>
					{ linkLabel }
				</a>
			</p>
		</div>
	);
}
Image
affiliate-block-cài đặt link button

Tới đây bạn sẽ được kết quả như hình trên.

Bước 9 : Thêm Block Style

9.1. Thêm style cho block tại file block.json

"styles": [
	{
		"name": "default",
		"label": "Default",
		"isDefault": true
	},
	{
		"name": "border",
		"label": "Border"
	}
],

Với điều bạn vừa thêm một style mặc định và một kiểu bổ sung được gọi là Border. Bây giờ quay lại editor để nhìn thấy sự thay đổi

Image
Thêm Style cho block

Tại đây bạn có thể chọn lựa bằng Styles panel trong Block Settings Sidebar.

Khi chọn 1 style, thẻ p sẽ có sự thay đổi về class theo định dạng

is-style-{style-name}

9.2. Thay đổi style trong editor.scss và style.scss

Với editor.scss

.wp-block-my-affiliate-plugin-my-affiliate-block {
	padding: 2px;
	&.is-style-default{
		border: 0;
	}
	&.is-style-border{
		border: 1px solid #000;
	}
}

và style.scss

.wp-block-my-affiliate-plugin-my-affiliate-block {
	&.is-style-default{
		border: 0;
	}
	&.is-style-border{
		border: 1px solid #000;
	}
}

Sau đó sử dụng lệnh npm run start để kiểm tra style đã thay đổi

Bước 10: Lồng các Gutenberg Block với nhau bằng component InnerBlocks

Affiliate Block mặc dù đã có đầy đủ tính năng, nhưng vẫn chưa hay lắm. Vậy nên bước này sẽ giới thiệu bạn cách làm cho nó có thể tạo được colum và upload ảnh bằng cách lồng block với nhau.

10.1. Tạo file container.js và import đến index.js

import './container';

trong file container.js bạn import các component 

import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import {
	useBlockProps, 
	InnerBlocks 
} from "@wordpress/block-editor";

Bước tiếp theo là tạo một template mẫu cung cấp cấu trúc mà các block sẽ được đặt bên trong.

Trong ví dụ này, chúng ta tạo một template bao gồm hai cột chứa block Hình ảnh cốt lõi và block Đơn vị liên kết tùy chỉnh ở trên:

const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
	[ 'core/column', { templateLock: 'all' }, [
		[ 'core/image' ],
	] ],
	[ 'core/column', { templateLock: 'all' }, [
		[ 'my-affiliate-plugin/my-affiliate-block', { placeholder: 'Enter side content...' } ],
	] ],
] ] ];

Xem thêm Block Template tại đây.

10.2. Tạo block cho Template trong container.js

registerBlockType('my-affiliate-plugin/my-affiliate-container-block', {
	title: __( 'Container', 'my-affiliate-block' ),
	category: 'design',

	edit( { className } ) {
		
		return(
			<div className={ className }>
				<InnerBlocks
					template={ TEMPLATE }
					templateLock="all"
				/>
			</div>
		)
	},

	save() {
		const blockProps = useBlockProps.save();
		return(
			<div { ...blockProps }>
				<InnerBlocks.Content />
			</div>
		)
	},
});

Vì phạm vi bài viết có giới hạn nên chỉ giới thiệu đến đây, bạn có thể xem chi tiết bài viết tại đây với các hướng dẫn còn lại với các thành phần khác hoặc xem full code trong link này.

Link Github

Đây chỉ là bài học đơn giản tạo một Gutenberg block, sau khi bạn hiểu cơ bản bạn có thể phát triển thành bất cứ block nào bạn thích.