Tạo block Card trong Gutenberg

Giới thiệu

Trong bài viết trước mình có giới thiệu về page builder Gutenburg sắp tích hợp vào WordPress và cách để tạo 1 plugin code các block nhúng vào trong page builder này (Link). Bài viết nãy mình sẽ hướng dẫn cụ thể cách tạo 1 block, mà ở đây là 1 block Card, sẽ có các tính năng là Nhập ảnh, tiêu đề và nội dung để hiển thị trên trình soạn thảo và ngoài trang Frontend phía người dùng.

Bắt đầu

Cấu trúc thư mục

Chi tiết về cấu trúc thư mục thì mình đã nói rõ trong bài viết trước, mình sẽ tạo 1 thư mục card-block nằm trong thư mục src, cụ thể như sau

first-block/src --card-block  ----block.js  ----style.scss  ----editor.scss 

hoặc xem ảnh sau, phần thêm là phần mình bôi viền đỏ:

Javascript

Trong file src/blocks.js cần import file card-block/block.js vừa tạo, thêm dòng sau vào cuối file. Code để tạo block sẽ nằm trong file card-block/block.js này.

import './card-block/block.js'; 

Ở file card-block/block.js, gọi một số component cần thiết trong ví dụ

const { RichText, MediaUpload, PlainText } = wp.editor; // Gọi 1 số component từ Editor const { registerBlockType } = wp.blocks; // Gọi component đăng ký block const { Button } = wp.components; // Gọi component Button 

Tiếp theo là import các file style đã được tạo

import './style.scss'; import './editor.scss'; 

Đăng ký block card, khai báo với Gutenberg rằng tôi muốn đăng ký 1 block có tiêu đề là Card, với icon heart (icon này dùng bộ Dashicon của WordPress), nằm trong category common của Gutenberg.

registerBlockType('first-block/card', {      title: 'Card',   icon: 'heart',   category: 'common' }); 

Tiếp theo khai báo một số thuộc tính có thể chỉnh sửa nội dung của block, nó hoạt động tương tự với state của ReactJS với phương thức setAttributes để cập nhật các thuộc tính đó, đoạn code này viết tiếp vào đoạn ở trên, phía dưới phần category: 'common' và được thêm dấu , sau common

attributes: {   title: {     source: 'text',     selector: '.card__title'   },   body: {     type: 'array',     source: 'children',     selector: '.card__body'   },   imageAlt: {     attribute: 'alt',     selector: '.card__image'   },   imageUrl: {     attribute: 'src',     selector: '.card__image'   } } 

Thên edit function ở phía sau phần attributes ở trên (nhớ kèm theo dấu , ở sau dấu đóng ngoặc nhọn }). Function này sẽ trả về phần sẽ hiển thị trên trình soạn thảo.

edit({ attributes, className, setAttributes }) {      // Khai báo dữ liệu trả về cho ImageButton. Có link ảnh sẽ hiển thị ra ảnh, nếu không sẽ hiển thị ra button chọn ảnh     const getImageButton = (openEvent) => {       if(attributes.imageUrl) {         return (           <img              src={ attributes.imageUrl }             onClick={ openEvent }             className="image"           />         );       }       else {         return (           <div className="button-container">             <Button                onClick={ openEvent }               className="button button-large"             >               Chọn Ảnh             </Button>           </div>         );       }     };      // Trả về dữ liệu để hiển thị lên trình soạn thảo     return (       <div className="container">         // Component này có nhiệm vụ hiển thị button Chọn Ảnh hoặc hiển thị ảnh đã được chọn          <MediaUpload           onSelect={ media => { setAttributes({ imageAlt: media.alt, imageUrl: media.url }); } } // Khi chọn ảnh các attributes sẽ được cập nhật           type="image"           value={ attributes.imageID }           render={ ({ open }) => getImageButton(open) }         />         // Component này hiển thị ra inputtext để nhập tiêu đề, và set dữ liệu khi nhập vào inputtext         <PlainText           onChange={ content => setAttributes({ title: content }) }           value={ attributes.title }           placeholder="Your card title"           className="heading"         />         // Component này hiển thị ra textarea để nhập nội dung của box, tương tự với các component trên, nó cũng set dữ liệu khi người dùng nhập thông tin.         <RichText           onChange={ content => setAttributes({ body: content }) }           value={ attributes.body }           multiline="p"           placeholder="Your card text"           formattingControls={ ['bold', 'italic', 'underline'] }           isSelected={ attributes.isSelected }         />       </div>     );    }, 

Tiếp theo là function save. Đây là function để xác định sẽ lưu gì vào database, mà cụ thể là trường post_content của post/page.

save({ attributes }) {    // Function hiển thị Ảnh   const cardImage = (src, alt) => {     if(!src) return null;      if(alt) {       return (         <img            className="card__image"            src={ src }           alt={ alt }         />        );     }          // No alt set, so let's hide it from screen readers     return (       <img          className="card__image"          src={ src }         alt=""         aria-hidden="true"       />      );   };      // Function hiển thị HTML sẽ được lưu vào database   return (     <div className="card">       { cardImage(attributes.imageUrl, attributes.imageAlt) }       <div className="card__content">         <h3 className="card__title">{ attributes.title }</h3>         <div className="card__body">           { attributes.body }         </div>       </div>     </div>   ); } 

Style

Thêm 1 chút style để block hiển thị đẹp hơn trên trình soạn thảo, mở file card-block/editor.scss và sửa thảnh:

 .gutenberg {        .container {     border: 1px solid #ccc;     padding: 1rem;   }    .button-container {     text-align: center;     padding: 22% 0;     background: #ccc;     border: 1px solid #f1f1f1;     border-radius: 2px;     margin: 0 0 1.2rem 0;   }    .heading {     font-size: 1.5rem;     font-weight: 600;   }    .image {     height: 15.7rem;     width: 100%;     object-fit: cover;   } } 

Kết quả

Đây là kết quả của ví dụ trên, bài viết sau mình sẽ hướng dẫn các bạn sử dụng block và render dữ liệu động, hẹn gặp lại các bạn nhé

Tham khảo: here

Leave a Reply

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>