446
0

[ WordPress ] Tạo block Gutenberg sử dụng MediaPlaceHolder và RichText

446
gutenberg-1
Thời gian đọc: 5 phút

Chào các bạn cũng lâu rồi nhỉ? Mình mới viết thêm blog mới chia sẻ kinh nghiệm làm việc cũng như kỹ năng lập trình của team với mọi người. Với bài viết kỳ này team mình đem đến màu blog mới cũng như theo xu hướng hiện giờ WordPress đang phát triển theo – Gutenberg.

Khái quát về components và tạo blocks sử dụng MediaPlaceHolder, RichText

Để các bạn hiểu rõ hơn những gì Gutenberg mang lại đối với lập trình viên WordPress, team mình hướng dẫn các bạn sử dụng Media PlaceHolder và RichText của WordPress. Về phần setup để bắt đầu viết block các bạn có thể xem ở bài [Gutenberg ] Tạo Block Gutenberg đầu tiên

Media placeholder component là gì ?

wordpress-gutenberg-mediaplaceholder
Media placeholder là component của Gutenberg WordPress, hỗ trợ developer có thể tạo field chọn hình ảnh của user trong khung giao diện block editor. Component cho phép user có thể upload từ máy tình hoặc import ảnh từ url bất kỳ, ngoài ra user cũng có thể chọn ảnh từ media của website.

Để sử dụng component chúng ta cần phải import Component từ wordpress như block code sau:

const { MediaPlaceholder } = wp.blockEditor
// Hoặc có thể import như sau:
// import { MediaPlaceholder } from '@wordpress/block-editor';
...
edit: ( { attributes, setAttributes } ) => {
return <>
    <MediaPlaceholder
    onSelect = {
                ( el ) => {
                    setAttributes( { theImage: el.url } );
                }
            }
            allowedTypes = { [ 'image' ] }
            multiple = { false }
            labels = { { title: 'The Image' } }
    />
</>
}

Mình giải thích rõ hơn về các props trong component này:

accept

Đây là props để chúng ta define được loại media nào được upload lên ví dụ: image/*,video/*.

allowedTypes

Props này giúp chúng ta có thể cho phép user upload các dạng file media( picture, text, video,… ) ví dụ: audio/mpeg, image/gif.

className

Props này giúp chúng ta đặt class cho PlaceHolder để tiện styling hoặc viết js.

multiple

Props này giúp chúng ta cho phép user upload và chọn được nhiều hay 1 file ảnh trong 1 lần chọn.

onError

Props này sẽ gọi callback function để xử lý khi upload file bị lỗi

onFilesPreUpload

Props này sẽ gọi callback function để xử lý trước khi file ảnh được upload vào media

onSelect

Props này để gọi callback sau khi file được upload lên media manager của wordpress.

value

Props này để register variables của media.

onSelectURL

Props này để xử lý sau khi user nhập image URL vào field.

Đây là 1 số props mình thấy hay dùng tới ngoài ra còn một số props khác các bạn có thể tra cứu tại đây.

RichText Component là gì ?

RichText là là component của Gutenberg WordPress, hỗ trợ developer có thể tạo field cho phép user nhập text, 1 đoạn văn bản hoặc nhiều đoạn văn bản,… với các tính năng chỉnh text như, căn lề, in nghiêng chữ, in đậm chữ, ganh dưới chữ,…
Để sử dụng component chúng ta cần phải import Component từ wordpress như block code sau:

const { RichText } = wp.blockEditor
// Hoặc có thể import như sau:
// import { RichText } from '@wordpress/block-editor';
attributes: {
        content: {
            type: 'string',
            source: 'html',
            selector: 'h3',
        },
    },
// Các thể có thể selector: p, h1, h2, h3, h4, h5, h6, span
    edit( { className, attributes, setAttributes } ) {
        return (
            <RichText
                tagName="h3"
                className={ className }
                value={ attributes.content }
                onChange={ ( content ) => setAttributes( { content } ) }
            />
        );
    },

    save( { attributes } ) {
        return <RichText.Content tagName="h3" value={ attributes.content } />;
    }
}

Mình giải thích rõ hơn về các props trong component này:

tagName

Đây là props để chúng ta define selector của RichText, và việc define này phải giống hoàn toàn với giá trị chúng ta đã khai báo ở attributes

className

Tương tự như Component trên thì props này để đat class cho selector của RichText lúc render ở editor admin và frontend.

onChange

Đây là props sẽ gọi callback function handle khi user nhập ký tự vào fields

placeholder

Đây là props thêm placeholder vào RichText

multiline

Props này chúng ta có thể phép user nhập text thành nhiều hàng hoặc không.

Đây là 1 số props mình thấy hay dùng tới ngoài ra còn một số props khác các bạn có thể tra cứu tại đây.

Tạo block CTA card

Trước tiên chúng ta cần phải register block với wordpress thông qua hàm registerBlockType

const { registerBlockType } = wp.blocks
const { __ } = wp.i18n
//import { registerBlockType } from '@wordpress/blocks'

registerBlockType(slug, {
            title: 'CTA Wolfactive block',
            description: 'This CTA Wolfactive block for my website',
            category: 'wolfactive',
            icon: 'dashicons-admin-site',
           keywords: [
                __('cta', 'wolfactive'),
                __("Wolfactive", 'wolfactive'),
                __('Home', 'wolfactive'),
            ],
            attributes:{

            },
            edit: function({ attributes, setAttributes }){

            },
            save: function({ attributes }){

            },
        })

Sau khi các bạn refesh lại editor thì các bạn sẽ thấy block đã tạo ví dụ như hình ảnh sau:

gutenbergs-cta-block-wolfactive

Tiếp theo chúng ta đi tiếp các tạo function cho edit. Đây là function để render component cũng như các tính năng điều chỉnh block trong editor của admin

const { registerBlockType } = wp.blocks
const { __ } = wp.i18n
const {Spinner} = wp.components
const {isBlobURL} = wp.blob
const {RichText, InspectorControls,MediaPlaceholder} = wp.blockEditor

//import { registerBlockType } from '@wordpress/blocks'
//import { __ } from '@wordpress/i18n'
//import {isBlobURL} from "@wordpress/blob";
//import {Spinner} from "@wordpress/components";
//import {RichText, InspectorControls,MediaPlaceholder} from "@wordpress/blockEditor";

registerBlockType(slug, {
            title: 'CTA Wolfactive block',
            description: 'This CTA Wolfactive block for my website',
            category: 'wolfactive',
            icon: 'dashicons-admin-site',
           keywords: [
                __('cta', 'wolfactive'),
                __("Wolfactive", 'wolfactive'),
                __('Home', 'wolfactive'),
            ],
            attributes:{
                    title:{
                        type: 'string',
                        source: 'html',
                        selector: 'h2',
                    },
                    image:{
                        type:'object',
                        default:{
                            url: '',
                            id:'',
                            alt:''
                        }
                    },
                buttonContext:{
                        type: 'string',
                        source: 'html',
                        selector: 'h2',
                    },
                    buttonURL:{
                        type:'string',
                    }
            },
            edit: function({ attributes, setAttributes }){
                const {title,image,buttonURL,buttonContext} = attributes
                return <>
                    <InspectorControls>
                        <PanelBody>
                        <URLInput
                            value={ buttonURL }
                            onChange={ ( url ) => setAttributes( { buttonURL: url || 'Click here' } ) }
                        />
                        </PanelBody>
                </InspectorControls>
                    <div className="wa-cta">
                        <div className="wa-cta__container wa-container">
                            {image.url ?
                                        <>
                                            <div className={`wa-cta__image wp-image-${image.id}`}>
                                                <img src={image.url} alt={image.alt} />
                                            </div>
                                            {isBlobURL(image.url) &&  <Spinner/>}
                                        </>
                                        :
                                        <MediaPlaceholder
                                            icon="format-image"
                                            onSelect={({id, url,alt}) => setAttributes({image: {
                                                url: url,
                                                id:id,
                                                alt:alt
                                            }})}
                                            onError={error => console.log(error)}
                                            accept="image/*"
                                            allowedTypes={['image']}
                                        />
                                    }
                            <RichText
                                tagName={'h3'}
                                className="wa-cta__heading"
                                onChange={(title)=> setAtrributes({heading})}
                                value={title}
                                placeholder={__('Enter Title...', 'wolfactive')}
                                keepPlaceholderOnFocus={true}
                            />
                           <div className=""wa-cta__btn" >
                                        <a href={buttonURL}
                                           className=""wa-primary-button"
                                        >
                                            <RichText
                                                tagName={'span'}
                                                className=""
                                                onChange={(buttonContext)=> setAtrributes({buttonContext})}
                                                value={buttonContext}
                                                placeholder={__('Enter Context Button...', 'wolfactive')}
                                                keepPlaceholderOnFocus={true}
                                            />
                                        </a>
                                    </div>
                        </div>
                    </div>
                    </>
            },
            save: function({ attributes }){

            },
        })

Ở đây mình tạo các biến để lưu dữ liệu gồm title, image, buttonURL và buttonContext. Sau đó mình import thêm InspectorControl và PanelBody để chèn thêm field nhập URL cho button thông qua component URLInput, các bạn có thể đọc doument về component tại đây.

Sau cùng thì chúng ta đền phần save vào database của block:

const { registerBlockType } = wp.blocks
const { __ } = wp.i18n
const {Spinner} = wp.components
const {isBlobURL} = wp.blob
const {RichText, InspectorControls,MediaPlaceholder} = wp.blockEditor

//import { registerBlockType } from '@wordpress/blocks'
//import { __ } from '@wordpress/i18n'
//import {isBlobURL} from "@wordpress/blob";
//import {Spinner} from "@wordpress/components";
//import {RichText, InspectorControls,MediaPlaceholder} from "@wordpress/blockEditor";

registerBlockType(slug, {
            title: 'CTA Wolfactive block',
            description: 'This CTA Wolfactive block for my website',
            category: 'wolfactive',
            icon: 'dashicons-admin-site',
           keywords: [
                __('cta', 'wolfactive'),
                __("Wolfactive", 'wolfactive'),
                __('Home', 'wolfactive'),
            ],
            attributes:{
                    title:{
                        type: 'string',
                        source: 'html',
                        selector: 'h2',
                    },
                    image:{
                        type:'object',
                        default:{
                            url: '',
                            id:'',
                            alt:''
                        }
                    },
                buttonContext:{
                        type: 'string',
                        source: 'html',
                        selector: 'h2',
                    },
                    buttonURL:{
                        type:'string',
                    }
            },
            edit: function( ){},
            save: function({ attributes }){
                 const {title,image,buttonURL,buttonContext} = attibutes;
                return <>
                    <div className="wa-cta">
                        <div className="wa-cta__container wa-container">
                            {image.url &&
                                        <>
                                            <div className={`wa-cta__image wp-image-${image.id}`}>
                                                <img src={image.url} alt={image.alt} />
                                            </div>
                                            {isBlobURL(image.url) &&  <Spinner/>}
                                        </>
                                    }
                            <RichText
                                tagName={'h3'}
                                className="wa-cta__heading"
                                value={title}
                            />
                           <div className=""wa-cta__btn" >
                                        <a href={buttonURL}
                                           className=""wa-primary-button"
                                        >
                                            <RichText.Content
                                                tagName={'span'}
                                                className=""
                                                value={buttonContext}
                                            />
                                        </a>
                                    </div>
                        </div>
                    </div>
                    </>
            },
        })

Kết luận

Vậy là mình đã giải thích và hướng dẫn các bạn sử dụng 2 component MediaPlaceholder và RichText trong việc tạo custom gutenbergs block. Cảm ơn các bạn đã theo dõi, hẹn gặp các bạn vào bài tới.