Chào mọi người đến với Series lập trình block Gutenberg trong WordPress. Series này giành cho những bạn thích Wordpess nhưng muốn tìm cảm giác làm theme, giao diện WordPress theo hướng mới mẻ không bị nhàm chán, thích làm giao diện trong CMS và trang web với React.
Với bài lần trước mình đã giới thiệu cách tạo Block Gutenberg đầu tiên. Thì bài viết này Hướng dẫn tạo block Gutenberg với dynamic content sẽ hướng dẫn các bạn từ block Gutenberg các bạn tạo ở bài trước sẽ thêm dynamic content, tùy chỉnh font-size, vân vân và mây mây…
Dynamic content với Component RichText
Tiếp tục với file heading/index.jsx
các bạn có thể tham khảo lại link này. Các bạn scroll lên đầu file import RichText vào block Heading.
import { RichText } from '@wordpress/editor'
Sau đó chúng ta cùng thêm thuộc tính attributes
vào hàm constructor
trong block heading
/*.........*/
class Heading extends Component {
constructor(props) {
super(props)
this.data = {
slug: 'themewa/heading',
title: __('Heading', 'wa-gutenberg'),
description: __('Heading create by Wolfactive', 'wa-gutenberg'),
category: 'page-wolfactive',
icon: (
<svg width="1em" height="1em" viewBox="0 0 512 512">
<path
d="M448 96v320h32a16 16 0 0 1 16 16v32a16 16 0 0 1-16 16H320a16 16 0 0 1-16-16v-32a16 16 0 0 1 16-16h32V288H160v128h32a16 16 0 0 1 16 16v32a16 16 0 0 1-16 16H32a16 16 0 0 1-16-16v-32a16 16 0 0 1 16-16h32V96H32a16 16 0 0 1-16-16V48a16 16 0 0 1 16-16h160a16 16 0 0 1 16 16v32a16 16 0 0 1-16 16h-32v128h192V96h-32a16 16 0 0 1-16-16V48a16 16 0 0 1 16-16h160a16 16 0 0 1 16 16v32a16 16 0 0 1-16 16z"
fill="currentColor"
/>
</svg>
),
keywords: [
__('Heading', 'wa-gutenberg'),
__('Wolf Active', 'wa-gutenberg'),
],
attributes: {
content: {
type: 'string',
source: 'html',
selector: 'p'
},
}
}
}
/* ............. */
}
export default Heading
Tiếp theo mình phải sửa lại hàm edit trong block heading
edit(){
return edit: ({ attributes, setAttributes}) => {
const {content} = attributes;
const onChangeContent = (content) =>{
setAttributes({content})
}
return(
<RichText
tagName="p"
className="rich-text"
onChange={onChangeContent}
value={content}
/>
)
}
}
Ở đây mình tạo hàm onChangeContent để có thể dynamic content khi user nhập vào RichText. Sau khi đã chỉnh xong hàm edit. Chúng ta cùng qua chỉnh hàm save
save: ({attributes}) =>{
const {content , alignment} = attributes;
return (
<RichText.Content
tagName="p"
value={content}
style={{textAlign : alignment}}
/>
);
}
Hàm Save sẽ lấy content được hàm edit setAttributes để lưu vào database của WordPress. Và bước cuối cùng là sửa lại hàm registerBlockType
init() {
let { slug, title, description, category, icon, keywords,attributes } = this.data
return registerBlockType(slug, {
title: title,
description: description,
category: category,
icon: icon,
keywords: keywords,
attributes: attributes,
edit: this.edit(),
save: this.save()
})
}
Và vậy là các bạn đã có thể nhập content bất kỳ và lưu vào database. Tuy nhiên dynamic content thôi thì cũng chưa đủ. Mình sẽ hướng dẫn các bạn thêm các tính năng khác như thay đổi font-size
, canh chỉnh lề. Tuy nhiên trước tiên cần phải refactor lại code do file này đã quá dài heading/index.jsx
P/s: Các bạn có thể tìm hiêu hơn về RichText tại đây
Refactor code cho block Heading
Lượt sơ qua file heading/index.jsx
thì có thể nhìn thấy hiện tại hàm edit đang rất dài nếu chúng ta thêm một số thuộc tính nữa sẽ còn dài thêm nên mình sẽ tách thành file riêng. Mình tạo file heading/edit.jsx
và bắt đầu import các package cần thiết để sử dụng.
import { Component} from '@wordpress/element'
import {
RichText,
} from '@wordpress/editor'
import { __ } from '@wordpress/i18n'
Copy và refactor code từ index.jsx
sang edit.jsx
class EditHeading extends Component {
constructor(props) {
super(props)
const { attributes } = this.props
this.state = {
attributes: attributes,
}
}
onChangeContent = (content) => {
this.props.setAttributes({ content })
}
render() {
const { attributes } = this.props
const { content} = attributes
return (
<RichText
tagName={'p'}
className="rich-text"
onChange={this.onChangeContent}
value={content}
placeholder={__('Enter Heading...', 'custom-block')}
keepPlaceholderOnFocus={true}
/>
)
}
}
export default EditHeading
Vào file index.jsx để sửa lại hàm edit
/*.........*/
import EditHeading from './edit'
/*.........*/
edit() {
return EditHeading
}
Vậy là chúng ta đã xong phần refactor code, tiếp tục đi đến phần thêm các tính năng như thay đổi font-size
, canh chỉnh lề
Thêm component FontSizePicker và AlignmentToolbar vào block heading
Trong file edit.jsx chúng ta thêm các component cần thiết cho việc thêm chức năng
import {
AlignmentToolbar,
BlockControls,
RichText,
FontSizePicker,
InspectorControls,
} from '@wordpress/editor'
Thêm các hàm cần thiết để bắt sự kiện change của các components
onChangeAlignment = (alignment) => {
this.props.setAttributes({ alignment })
}
onChangeFontSize = (fontSize) => {
this.props.setAttributes({ fontSize })
}
Chỉnh lại một chút phần return về từ file edit.jsx
return (
<>
<BlockControls>
<AlignmentToolbar
value={alignment}
onChange={this.onChangeAlignment}
/>
</BlockControls>
<InspectorControls>
<FontSizePicker
withSlider={true}
onChange={this.onChangeFontSize}
/>
</InspectorControls>
<RichText
tagName={'p'}
className="rich-text"
onChange={this.onChangeContent}
value={content}
style={{ textAlign: alignment, fontSize: fontSize }}
placeholder={__('Enter Heading...', 'custom-block')}
keepPlaceholderOnFocus={true}
/>
</>
)
Sau đó chúng ta vào lại file index.jsx để chỉnh sửa lại attributes và hàm save
- Thuộc tính attributes
attributes: { content: { type: 'string', source: 'html', selector: 'p', }, alignment: { type: 'string', }, fontSize: { type: 'number', }, },
- Hàm save
save() { return ({ attributes }) => { let { content, alignment, fontSize } = attributes return ( <> <RichText.Content tagName="p" value={content} className="rich-text" style={{ textAlign: alignment, fontSize: fontSize }} /> </> ) } }
Và đây là kết quả thu được
Tổng kết
Với bài này mình đã hướng dẫn các bạn cách khai báo và tạo block Gutenberg với dynamic content và thêm một số tính năng như chình
font-size
, canh lề. Tuy nhiên nếu hàm edit va hàm save trả về các thẻ HTML không giống nhau dẫn đến lỗi sẽ xảy ra trong lần reload vảo edit của post tiếp theo. Qua bài sau mình sẽ hướng dẫn các bạn giải quyết issue này.
Các bạn có thể tham khảo tổng quan về series tại đây
Cảm ơn các bạn đã đón đọc. Các bạn có thắc mắc hay có vấn đề cần giải đáp thì hay inbox vào fanpage Wolfactive nhé.