#phptek @salcode

Gutenberg Comes to WordPress

Sal Ferrarello / @salcode


salcode.com/phptek Jump to resources
Download PDF

Handmade birthday card.

Pictionary Board Game.

Lots of art supplies, paints, stamps, glitter, etc.

WordPress Legacy Editor Experience.

Block Based Editor

Animated gif of WordPress block based editor adding two paragraphs and a quote.

Animated gif of re-arranging WordPress blocks in the editor.

'post_content'


  <!-- wp:paragraph -->
  <p>This is a paragraph block.</p>
  <!-- /wp:paragraph -->

  <!-- wp:paragraph -->
  <p>This is another paragraph block.</p>
  <!-- /wp:paragraph -->

'post_content'


  <!-- wp:quote -->
  <blockquote class="wp-block-quote">
    <p>I was only ever wrong once
    and that was the time I
    thought I was wrong.</p>
    <cite>My Grandfather</cite></blockquote>
  <!-- /wp:quote -->

Whoa, slow down!

A runner falling.


  add_filter(
    'gutenberg_can_edit_post_type',
    '__return_false'
  );

or
the Disable Gutenberg Plugin

Block Toolbar

Screenshot of block toolbar.

Block Inspector
Controls

Screenshot of block inspector control.

Theme Support

functions.php


<?php
/**
 * Add support for .alignwide and .alignfull
 * CSS classes. Typically used on images.
 */
add_theme_support( 'align-wide' );

Toolbar with extra align wide and align full buttons.

Toolbar with extra align wide and align full buttons.

Color Control

Text color selector - default.

functions.php


add_theme_support( 'disable-custom-colors' );

add_theme_support( 'editor-color-palette',
    [
        'name'  => 'dark blue',
        'color' => '#007fbc',
    ]
);

Text color selector - with custom palette.

Test Drive

One Block, Many Pages

Shared blocks

Build Your
Own Block

A 2x4 red plastic brick like a Lego brick.

Requirements

  • ES6+
  • JSX
  • Webpack
  • Babel
  • npm
  • React

Requirements

  • ES6+
  • JSX
  • Webpack
  • Babel
  • npm
  • React

WP CLI


$ wp scaffold plugin my-plugin

$ wp scaffold block my-block \
	--plugin=my-plugin

$ wp plugin activate my-plugin

    my-plugin
    |-- my-plugin.php
    `-- blocks
        |-- my-block.php
        `-- my-block
            |-- editor.css
            |-- index.js
            `-- style.css


    my-plugin
    |-- my-plugin.php (root plugin file)
    `-- blocks
        |-- my-block.php
        `-- my-block
            |-- editor.css
            |-- index.js
            `-- style.css

my-plugin.php


  include(
    plugin_dir_path( __FILE__ ) .
    'blocks/my-block.php'
  );

Inserting my custom block in the Gutenberg editor, uneditable. Says, 'Hello from the editor!'

Editor appearance of WP CLI generated block without modifications, 'Hello from the editor!'.

On The Front-end

Output of WP CLI generated block without modifications, 'Hello from the saved content!'.

One object with two light sources resulting in two very different shadows.

'post_content'


  <!-- wp:my-plugin/my-block -->
  <p class="wp-block-my-plugin-my-block">
    Hello from the saved content!</p>
  <!-- /wp:my-plugin/my-block -->


    my-plugin
    |-- my-plugin.php
    `-- blocks
        |-- my-block.php
        `-- my-block
            |-- editor.css
            |-- index.js
            `-- style.css


    my-plugin
    |-- my-plugin.php
    `-- blocks
        |-- my-block.php (PHP for block)
        `-- my-block
            |-- editor.css
            |-- index.js
            `-- style.css

blocks/my-block.php

register_block_type( 'my-plugin/my-block', [

	'editor_script'  => 'myblock-block-editor',
	'editor_style'   => 'myblock-block-editor',
	'style'          => 'myblock-block',


] );

blocks/my-block.php

register_block_type( 'my-plugin/my-block', [

	'editor_script'  => 'myblock-block-editor',
	'editor_style'   => 'myblock-block-editor',
	'style'          => 'myblock-block',
	'render_callback'=> 'my_render_callback',

] );

blocks/my-block.php

function my_render_callback( $attributes ) {

	return sprintf(
		'<pre><code>%s</code></pre>',
		'My rendered output'
	);

}

On The Front-end

Screenshot of resulting output on front-end that says 'My rendered output'.

blocks/my-block.php

function my_render_callback( $attributes ) {

	return sprintf(
		'<pre><code>%s</code></pre>',
		'My rendered output'
	);

}

blocks/my-block.php

function my_render_callback( $attributes ) {

	return sprintf(
		'<pre><code>%s</code></pre>',
		esc_html( get_the_author() )
	);

}

On The Front-end

Screenshot of resulting output on front-end that displays the author name, 'Sal Ferrarello'.

[shortcode]

blocks/my-block.php

function my_render_callback( $attributes ) {

	return sprintf(
		'<pre><code>%s</code></pre>',
		esc_html( get_the_author() )
	);

}

blocks/my-block.php

function my_render_callback( $attributes ) {

	return sprintf(
		'<pre><code>%s</code></pre>',
		print_r( $attributes, true )
	);

}

On The Front-end

Screenshot of resulting output on front-end showing an empty array.

$attributes argument is an empty array

blocks/my-block.php

register_block_type( 'my-plugin/my-block', [
	'editor_script'  => 'myblock-block-editor',
	'editor_style'   => 'myblock-block-editor',
	'style'          => 'myblock-block',
	'render_callback'=> 'my_render_callback',



] );

blocks/my-block.php

register_block_type( 'my-plugin/my-block', [
	'editor_script'  => 'myblock-block-editor',
	'editor_style'   => 'myblock-block-editor',
	'style'          => 'myblock-block',
	'render_callback'=> 'my_render_callback',
	'attributes'     => [
		'val' => [],
	],
] );

On The Front-end

Screenshot of resulting output on front-end show an array with one key, 'val', and no value.

The End
of avoiding JavaScript

    my-plugin
    |-- my-plugin.php
    `-- blocks
        |-- my-block.php
        `-- my-block
            |-- editor.css
            |-- index.js
            `-- style.css
    my-plugin
    |-- my-plugin.php
    `-- blocks
        |-- my-block.php
        `-- my-block
            |-- editor.css
            |-- index.js (block JavaScript)
            `-- style.css
( function( wp ) {




} )( window.wp );

blocks/my-block/index.js

var el = wp.element.createElement;

var __ = wp.i18n.__;

var registerBlockType =
	wp.blocks.registerBlockType;

blocks/my-block/index.js

  registerBlockType(
    'my-plugin/my-block',
    {
      title: __( 'My block' ),
      edit: function( props ) {},
      save: function( props ) {}
    }
  );

blocks/my-block/index.js

registerBlockType()

blocks/my-block.php

register_block_type()

Animated gif from Godfather 3, 'Just when I thought I was out, they pull me back in.'

blocks/my-block/index.js

  registerBlockType(
    'my-plugin/my-block',
    {
      title: __( 'My block' ),
      edit: function( props ) {},
      save: function( props ) {}
    }
  );

blocks/my-block/index.js

  registerBlockType(
    'my-plugin/my-block',
    {
      title: __( 'My block' ),
      edit: function( props ) {},
      save: function(props) { return null; }
    }
  );

'post_content'


  <!-- wp:my-plugin/my-block /-->

blocks/my-block/index.js

  registerBlockType(
    'my-plugin/my-block',
    {
      title: __( 'My block' ),
      edit: function( props ) {},
      save: function(props) { return null; }
    }
  );
edit: function( props ) {
	return el(
		'p',
		{ className: props.className },
		__( 'Hello from the editor!' )
	);
},
edit: function( props ) {
	return wp.element.createElement(
		'p',
		{ className: props.className },
		__( 'Hello from the editor!' )
	);
},
edit: function( props ) {
	return React.createElement(
		'p',
		{ className: props.className },
		__( 'Hello from the editor!' )
	);
},

Editor appearance of WP CLI generated block without modifications, 'Hello from the editor!'.

'post_content'

  <p class="wp-block-my-plugin-my-block">
    Hello from the editor!
  </p>

React

Person wearing virtual reality goggles.


return el(
	'p',
	{
		className: props.className



	},
	__( 'Hello from the editor!' )
);

return el(
	wp.components.TextControl,
	{
		className: props.className,



		value: props.attributes.val
	}
);

return el(
	wp.components.TextControl,
	{
		className: props.className,
		onChange: function( newVal ) {
			props.setAttributes( { val: newVal });
		},
		value: props.attributes.val
	}
);

In the Editor

Screenshot of input field in the WordPress editor block we created.

On the Front-end

Screenshot of resulting output on front-end show an array with one key, 'val' with the value we set in the editor block.

'post_content'


  <!-- wp:my-plugin/my-block /-->



'post_content'


  <!-- wp:my-plugin/my-block
	  {"val":"Now I have editable content.
	  I editted this."} /-->

Static Blocks

  • Remove render_callback in PHP
  • Modify JavaScript save function

blocks/my-block/index.js

save: function() {
	return el(
		'p',
		{},
		__( 'Hello from the saved content!' )
	);
},

blocks/my-block/index.js

save: function( props ) {
	return el(
		'p',
		{},
		__( 'Hello from the saved content!' )
	);
},

blocks/my-block/index.js

save: function( props ) {
	return el(
		'p',
		{},
		props.attributes.val
	);
},

Source of truth ?

'post_content'



  <!-- wp:my-plugin/my-block {"val":"Now I
  have editable content. I editted this."}-->
  <p class="wp-block-my-plugin-my-block">
  Now I have editable content.
  I editted this.</p>
  <!-- /wp:my-plugin/my-block -->


Source of truth ?

'post_content'


  <!-- wp:my-plugin/my-block {"val":"Now I
  have editable content. I editted this."}-->

  <p class="wp-block-my-plugin-my-block">
  Now I have editable content.
  I editted this.</p>

  <!-- /wp:my-plugin/my-block -->

Block modified externally, error message.

blocks/my-block.php

register_block_type( 'my-plugin/my-block', [
	...
	'attributes' => [
		'val' => [],



	],
] );

blocks/my-block.php

register_block_type( 'my-plugin/my-block', [
	...
	'attributes' => [
		'val' => [
			'selector' => 'p',
			'source'   => 'text',
		],
	],
] );

'post_content'


  <!-- wp:my-plugin/my-block -->

  <p class="wp-block-my-plugin-my-block">
  Now I have editable content.
  I editted this.</p>

  <!-- /wp:my-plugin/my-block -->

Happy Birthday Output from WordPress Gutenberg Cake Block.

cake block attributes

  'attributes' => [
    'message' => [
      'selector' => 'h3',
      'source'   => 'text',
    ],
    'name' => [
      'selector' => '.name',
      'source'   => 'text',
    ],
  ],

Iron Code Studio

Sal Ferrarello

ironco.de/presentations/gutenberg

@salcode

Screen recording of inserting Cake Block and modifying.

ES6+, JSX, Babel, Webpack block template


	$ create-guten-block
	

Resources

Image Credits