KEMBAR78
Custom gutenberg block development in react | PPTX
Gutenberg Blocks
Design Reuse
Editing
Experience
Ways of building Gutenberg Blocks
ES 5
ESNext &
JSX
Why write blocks in ES6/ESNext?
Arrows
Block
Scoping
Modules
Classes
Promises
ES5
ES5 ESNext
ES5 ESNext
Adding JSX
What is JSX?
Adding JSX
● JavaScript XML
● A syntax that blends HTML and JavaScript.
● Provides syntactic sugar for the React.createElement() or
wp.element.createElement() in Gutenberg.
JSX Example
Type of Component
JSX Example
Type of Component
Lowercase letter: Built in component
Capitalized: React Component
ES5 ESNext
ES5 ESNext + JSX
Why write blocks in ES6/ESNext?
Easy to Read & Write Code
Why write blocks in ES6/ESNext?
Prevents need
for globals Shorter Syntax
Functions
Why write blocks in ES6/ESNext?
● Simpler Code - Easy to read and write.
● Shorter Syntax using Arrow functions.
● Organize your code into smaller modules.
● Anticipate and prevent need of globals.
Why write blocks in ES6/ESNext?
● Block Scoping solves possible scoping ambiguity.
● Promises provide improved readability via methods
chaining and succinct error handling
Challenges
● Requires an extra build step for code transformation.
● ES5 without JSX can run straight in the browser.
● Locating and understanding the compiled source code is
difficult.
● Tooling around JavaScript could be intimidating.
Browser support
Solution
@wordpress/scripts
A collection of reusable scripts for
WordPress Development.
Features of @wordpress/scripts
● Abstracts required libraries away to standardize and
simplify development.
● Handles the dependencies and default configuration for
webpack and Babel.
● Linting tools for JavaScript and Css.
● Code testing using jest.
● Check required licence and engines.
Block Development
Build blocks in 3
steps
1.Installing Packages
Install packages with @wordpress/scripts
mkdir custom-blocks
cd custom-blocks
npm init --yes
npm i --save-dev @wordpress/scripts
mkdir src
touch index.php src/index.js src/editor.css src/style.css
Directory Structure
├── node_modules
├── package-lock.json
├── package.json
└── src
├── editor.css
├── style.css
└── index.js
├── index.php
Install packages with @wordpress/scripts
Entry point : src/index.js
Output: build/index.js ( enqueue this file )
Add scripts in package.json
"scripts": {
"build": "wp-scripts build",
"start": "wp-scripts start"
},
npm run start
Directory structure after build
├── build
│ └── index.js
├── node_modules
├── package-lock.json
├── package.json
└── src
├── editor.css
├── index.js
└── style.css
├── index.php
Register Block
Client Side
Register block client side
const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;
registerBlockType( 'gtcb-blocks/custom-block', { key: value } );
Block name Block configuration object
Register block client side
import { __ } from ‘@wordpress/i18n’;
import { registerBlockType } from ’@wordpress/blocks’;
registerBlockType( 'gtcb-blocks/custom-block', {
title: __( 'Custom Block', 'custom-blocks' ),
icon: 'megaphone',
category: 'common',
edit: () => ( <div>Hello World</div> ),
save: () => ( <div>Hello World</div> )
} );
Edit function
● Describes the structure of the block
● Represents what the editor will render when the block is
used on the editor.
edit: () => ( <div>Hello World</div> ),
Save function
● Decides how your content would look at the front end.
● Defines how the attribute will combine together to
generate a final mark-up.
● Mark up then serialized and saved into the database
save: () => ( <div>Hello World</div> ),
Run the script
Directory structure after build
├── build
│ └── index.js
│ └── index.assets.php
├── node_modules
├── package-lock.json
├── package.json
└── src
├── editor.css
├── index.js
└── style.css
├── index.php
index.assets.php
<?php return array('dependencies' => array('wp-block-editor',
'wp-blocks', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' =>
'26c91f40469d04ed5d7bcff9ec3e126d');
Register Scripts & Styles
/**
* The 'enqueue_block_assets' hook includes styles and scripts both in
editor and
* frontend, except when is_admin() is used to include them
conditionally
*/
add_action( 'enqueue_block_assets', 'enqueue_editor_assets' );
Register Scripts
function enqueue_editor_assets() {
$asset_config_file = sprintf( '%s/index.asset.php', GTCB_BUILD_PATH );
$asset_config = require_once $asset_config_file;
wp_enqueue_script(
'gtcb-blocks-js',
GTCB_BUILD_URI . '/index.js',
$asset_config[‘dependencies’],
$asset_config[‘version’],
true
);
}
Register styles
…..
// Block editor styles.
wp_register_style(
'gtcb-blocks-css',
GTCB_BLOCKS_URL . '/src/style.css',
[ 'wp-block-library-theme', 'wp-block-library', ],
filemtime( GTCB_BLOCKS_PATH . '/src/editor.css' )
);
Dependencies
● wp-blocks : includes block type registration and related
functions.
● wp-element : includes the WordPress Element abstraction for
describing the structure of your blocks.
● wp-block-editor : includes components like RichText,
MediaUpload etc
State of a Block
State
● A state is a plain JavaScript object.
● A state of a block is maintained through the editing
session.
● To achieve dynamic change in the block’s structure when
the user changes a block.
● Everytime a block is updated edit function is called.
Post saved in database
<!-- wp:gtcb-blocks/custom-block -->
<div class="wp-block-gtcb-blocks-custom-block" >Hello World</div>
<!-- /wp:gtcb-blocks/custom-block -->
Block name
Attributes
Attributes
● Help you extract block attribute values from saved post
content.
● Map from the saved markup to a JavaScript
representation of a block.
● Attribute sources are a superset of functionality
provided by hpq
Attributes
● hpq: A small library used to parse and query HTML
markup into an object shape.
● When you define these attributes into
registerBlockType(), it is passed to the edit() and save()
Define Attributes
registerBlockType( 'gtcb-blocks/custom-block', {
...
attributes: {
fullName: {
type: 'array',
source: 'children',
selector: 'p'
},
},
look for the text inside of selector
Attributes passed to edit() and save()
edit: ( props ) => {
console.log( props );
return ( <div>Hello World</div> )
},
save: ( props ) => {
return ( <div>Hello World</div> )
},
Let’s console props
attributes:
fullName: []
className: "wp-block-gtcb-blocks-custom-block"
name: "gtcb-blocks/custom-block"
setAttributes: ƒ ()
Reusable Components
Reusable Components
● Instead of creating DOM nodes using createElement(),
we can encapsulate this behavior using Components.
● Hide the complexity into their self-contained units
● Many blocks share the same complex behaviors
● Reusable Components simplify implementations of your
block’s edit function
● RichText, BlockControls, AlignmentToolbar,
RichText
RichText Component
import { RichText } from ‘@wordpress/block-editor’;
registerBlockType( 'gtcb-blocks/custom-block', {
….
edit: ( props ) => {
let { attributes: { fullName } , setAttributes, className } = props;
return (
<RichText
tagName="div"
placeholder={ __( 'Full Name', 'custom-blocks' ) }
value={ fullName }
onChange={ ( value ) => setAttributes( { fullName: value } ) }
className={ className }
/>
)
},
save: ( props ) => {
let { attributes: { fullName } , className } = props;
return (
<RichText.Content
tagName="div"
value={ fullName }
className={ className }
/>
)
},
registerBlockType( 'gtcb-blocks/custom-block', {
attributes: {
fullName: {
type: 'array',
source: 'children',
selector: 'div'
},
},
edit: ( props ) => {
let { attributes: { fullName } , setAttributes, className } = props;
return (
<RichText
tagName="div"
placeholder={ __( 'Full Name', 'custom-blocks' ) }
value={ fullName }
onChange={ ( value ) => setAttributes( { fullName: value } ) }
className={ className }
/>
)
},
save: ( props ) => {
let { attributes: { fullName }, className } = props;
return (
<RichText.Content
tagName="div"
value={ fullName }
className={ className }
/>
)
User enters the data:
edit ()
User saves the data:
save ()
More Ways of building Blocks
● @wordpress/create-block
Third Party Libraries
● Editor Blocks
● Gutenberg Hub
● Gutenberg Cloud
WordPress Core for
Gutenberg
Gutenberg Core
● registerBlockType() resides in
https://github.com/WordPress/gutenberg/blob/master/
packages/blocks/src/api/registration.js.
● Components core files:
https://github.com/WordPress/gutenberg/blob/master/
packages/block-editor/src/components/
Git repo
● Git repo for this example
https://github.com/imranhsayed/custom-blocks
● Gutenberg Workshop
https://github.com/imranhsayed/gutenberg-workshop
Questions?
Questions?
Imran Sayed
@imranhsayed

Custom gutenberg block development in react

  • 2.
  • 3.
    Ways of buildingGutenberg Blocks ES 5 ESNext & JSX
  • 4.
    Why write blocksin ES6/ESNext? Arrows Block Scoping Modules Classes Promises
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
    Adding JSX ● JavaScriptXML ● A syntax that blends HTML and JavaScript. ● Provides syntactic sugar for the React.createElement() or wp.element.createElement() in Gutenberg.
  • 10.
  • 11.
    JSX Example Type ofComponent Lowercase letter: Built in component Capitalized: React Component
  • 12.
  • 13.
  • 14.
    Why write blocksin ES6/ESNext? Easy to Read & Write Code
  • 15.
    Why write blocksin ES6/ESNext? Prevents need for globals Shorter Syntax Functions
  • 16.
    Why write blocksin ES6/ESNext? ● Simpler Code - Easy to read and write. ● Shorter Syntax using Arrow functions. ● Organize your code into smaller modules. ● Anticipate and prevent need of globals.
  • 17.
    Why write blocksin ES6/ESNext? ● Block Scoping solves possible scoping ambiguity. ● Promises provide improved readability via methods chaining and succinct error handling
  • 18.
    Challenges ● Requires anextra build step for code transformation. ● ES5 without JSX can run straight in the browser. ● Locating and understanding the compiled source code is difficult. ● Tooling around JavaScript could be intimidating.
  • 19.
  • 20.
    Solution @wordpress/scripts A collection ofreusable scripts for WordPress Development.
  • 21.
    Features of @wordpress/scripts ●Abstracts required libraries away to standardize and simplify development. ● Handles the dependencies and default configuration for webpack and Babel. ● Linting tools for JavaScript and Css. ● Code testing using jest. ● Check required licence and engines.
  • 22.
  • 23.
  • 24.
  • 25.
    Install packages with@wordpress/scripts mkdir custom-blocks cd custom-blocks npm init --yes npm i --save-dev @wordpress/scripts mkdir src touch index.php src/index.js src/editor.css src/style.css
  • 26.
    Directory Structure ├── node_modules ├──package-lock.json ├── package.json └── src ├── editor.css ├── style.css └── index.js ├── index.php
  • 27.
    Install packages with@wordpress/scripts Entry point : src/index.js Output: build/index.js ( enqueue this file )
  • 28.
    Add scripts inpackage.json "scripts": { "build": "wp-scripts build", "start": "wp-scripts start" },
  • 29.
  • 30.
    Directory structure afterbuild ├── build │ └── index.js ├── node_modules ├── package-lock.json ├── package.json └── src ├── editor.css ├── index.js └── style.css ├── index.php
  • 31.
  • 32.
    Register block clientside const { __ } = wp.i18n; const { registerBlockType } = wp.blocks; registerBlockType( 'gtcb-blocks/custom-block', { key: value } ); Block name Block configuration object
  • 33.
    Register block clientside import { __ } from ‘@wordpress/i18n’; import { registerBlockType } from ’@wordpress/blocks’; registerBlockType( 'gtcb-blocks/custom-block', { title: __( 'Custom Block', 'custom-blocks' ), icon: 'megaphone', category: 'common', edit: () => ( <div>Hello World</div> ), save: () => ( <div>Hello World</div> ) } );
  • 34.
    Edit function ● Describesthe structure of the block ● Represents what the editor will render when the block is used on the editor. edit: () => ( <div>Hello World</div> ),
  • 35.
    Save function ● Decideshow your content would look at the front end. ● Defines how the attribute will combine together to generate a final mark-up. ● Mark up then serialized and saved into the database save: () => ( <div>Hello World</div> ),
  • 36.
  • 37.
    Directory structure afterbuild ├── build │ └── index.js │ └── index.assets.php ├── node_modules ├── package-lock.json ├── package.json └── src ├── editor.css ├── index.js └── style.css ├── index.php
  • 38.
    index.assets.php <?php return array('dependencies'=> array('wp-block-editor', 'wp-blocks', 'wp-element', 'wp-i18n', 'wp-polyfill'), 'version' => '26c91f40469d04ed5d7bcff9ec3e126d');
  • 39.
    Register Scripts &Styles /** * The 'enqueue_block_assets' hook includes styles and scripts both in editor and * frontend, except when is_admin() is used to include them conditionally */ add_action( 'enqueue_block_assets', 'enqueue_editor_assets' );
  • 40.
    Register Scripts function enqueue_editor_assets(){ $asset_config_file = sprintf( '%s/index.asset.php', GTCB_BUILD_PATH ); $asset_config = require_once $asset_config_file; wp_enqueue_script( 'gtcb-blocks-js', GTCB_BUILD_URI . '/index.js', $asset_config[‘dependencies’], $asset_config[‘version’], true ); }
  • 41.
    Register styles ….. // Blockeditor styles. wp_register_style( 'gtcb-blocks-css', GTCB_BLOCKS_URL . '/src/style.css', [ 'wp-block-library-theme', 'wp-block-library', ], filemtime( GTCB_BLOCKS_PATH . '/src/editor.css' ) );
  • 42.
    Dependencies ● wp-blocks :includes block type registration and related functions. ● wp-element : includes the WordPress Element abstraction for describing the structure of your blocks. ● wp-block-editor : includes components like RichText, MediaUpload etc
  • 45.
  • 46.
    State ● A stateis a plain JavaScript object. ● A state of a block is maintained through the editing session. ● To achieve dynamic change in the block’s structure when the user changes a block. ● Everytime a block is updated edit function is called.
  • 47.
    Post saved indatabase <!-- wp:gtcb-blocks/custom-block --> <div class="wp-block-gtcb-blocks-custom-block" >Hello World</div> <!-- /wp:gtcb-blocks/custom-block --> Block name
  • 48.
  • 49.
    Attributes ● Help youextract block attribute values from saved post content. ● Map from the saved markup to a JavaScript representation of a block. ● Attribute sources are a superset of functionality provided by hpq
  • 50.
    Attributes ● hpq: Asmall library used to parse and query HTML markup into an object shape. ● When you define these attributes into registerBlockType(), it is passed to the edit() and save()
  • 51.
    Define Attributes registerBlockType( 'gtcb-blocks/custom-block',{ ... attributes: { fullName: { type: 'array', source: 'children', selector: 'p' }, }, look for the text inside of selector
  • 52.
    Attributes passed toedit() and save() edit: ( props ) => { console.log( props ); return ( <div>Hello World</div> ) }, save: ( props ) => { return ( <div>Hello World</div> ) },
  • 53.
    Let’s console props attributes: fullName:[] className: "wp-block-gtcb-blocks-custom-block" name: "gtcb-blocks/custom-block" setAttributes: ƒ ()
  • 54.
  • 55.
    Reusable Components ● Insteadof creating DOM nodes using createElement(), we can encapsulate this behavior using Components. ● Hide the complexity into their self-contained units ● Many blocks share the same complex behaviors ● Reusable Components simplify implementations of your block’s edit function ● RichText, BlockControls, AlignmentToolbar,
  • 56.
  • 57.
    RichText Component import {RichText } from ‘@wordpress/block-editor’; registerBlockType( 'gtcb-blocks/custom-block', { ….
  • 58.
    edit: ( props) => { let { attributes: { fullName } , setAttributes, className } = props; return ( <RichText tagName="div" placeholder={ __( 'Full Name', 'custom-blocks' ) } value={ fullName } onChange={ ( value ) => setAttributes( { fullName: value } ) } className={ className } /> ) },
  • 59.
    save: ( props) => { let { attributes: { fullName } , className } = props; return ( <RichText.Content tagName="div" value={ fullName } className={ className } /> ) },
  • 60.
    registerBlockType( 'gtcb-blocks/custom-block', { attributes:{ fullName: { type: 'array', source: 'children', selector: 'div' }, }, edit: ( props ) => { let { attributes: { fullName } , setAttributes, className } = props; return ( <RichText tagName="div" placeholder={ __( 'Full Name', 'custom-blocks' ) } value={ fullName } onChange={ ( value ) => setAttributes( { fullName: value } ) } className={ className } /> ) }, save: ( props ) => { let { attributes: { fullName }, className } = props; return ( <RichText.Content tagName="div" value={ fullName } className={ className } /> )
  • 61.
    User enters thedata: edit ()
  • 63.
    User saves thedata: save ()
  • 65.
    More Ways ofbuilding Blocks ● @wordpress/create-block
  • 66.
    Third Party Libraries ●Editor Blocks ● Gutenberg Hub ● Gutenberg Cloud
  • 67.
  • 68.
    Gutenberg Core ● registerBlockType()resides in https://github.com/WordPress/gutenberg/blob/master/ packages/blocks/src/api/registration.js. ● Components core files: https://github.com/WordPress/gutenberg/blob/master/ packages/block-editor/src/components/
  • 69.
    Git repo ● Gitrepo for this example https://github.com/imranhsayed/custom-blocks ● Gutenberg Workshop https://github.com/imranhsayed/gutenberg-workshop
  • 70.
  • 71.