single.php

Letztes Update am

Ein Gutenberg-Block ohne JSX, Babel, ES6 und weitere dicke Entwickler-Libraries

Der Block color-block bringt eine RichText-Komponente mit zwei Einstellungen unter der rechten Sidebar Block (InspectorControls): Hintergrundfarbe und Textfarbe.

Das Plugin besteht aus drei Dateien:

+—— color-block
|  +—— color-block.php
|  +—— color-block.js
|  +—— color-block.css

Block mit register_block_type() registrieren

Das Block-Plugin beginnt wie immer mit dem mehrzeiligen Kommentar.

<?php
/**
 * Plugin Name: Color Block
 * Description: Creates a Gutenberg Block to add a colored text component to the page.
 * Author: Emma und Ulrike
 * Author URI: https://colofon.de
 * Text Domain: jscolorblock
 * Version: 1.0.0
 */

Die PHP-Datei lädt den Block und die Stile aus color-block.js bzw. color-block.css mittels register_block_type.

wp_register_script

Wichtig:

wp_register_script lädt an keiner Stelle die Javascript-Datei. Die JS-Datei wird nur unter dem Handle verfügbar gemacht, damit sie an anderer Stelle später eingereiht – enqueue – werden kann.

$block_path = '/color-block.js';
// Registriert das Editor-Script des Blocks
wp_register_script(
	'jscolorblock-color-block',
	plugins_url( $block_path , __FILE__ ),
	[ 'wp-i18n', 'wp-element', 'wp-blocks', 'wp-components', 'wp-editor' ],
	filemtime( plugin_dir_path( $block_path , __FILE__ ) )
);

WordPress bevorratet Pakete, die im Block ausgeführt werden können, aber sie müssen vor dem Javascript geladen werden.

Im Beispiel bestehen die folgenden Abhängigkeiten:

  • wp-i18n – Wird für die Übersetzungen benötigt
  • wp-element – React & ReactDOM
  • wp-blocks – Mitsamt registerBlockTypes
  • wp-components – WP UI Component Library
  • wp-editor – Die RichText-Komponenten des Editors

Header

  • wp-i18n – Wird für die Übersetzungen benötigt

Absatz mit etwas Text

Header 2

  • wp-element – React & ReactDOM

Absatz mit etwas mehr Text als in eine Zeile passt

wp_register_style

Im Unterschied zu wp_register_script kann in der letzten Eigenschaft eine Funktion angegeben werden und es müssen keine Abhängigkeiten eingebaut werden. Ansonsten sind wp_register_style und wp_register_script ähnlich aufgebaut.

// creating a variable for our css file path
$style_path = '/color-block.css';
wp_register_style(
	'jscolorblock-color-block-styles',
	plugins_url( $style_path , __FILE__ ),
	[],
	filemtime( plugin_dir_path( $style_path , __FILE__ ) )
);

register_block_type

Genereller Aufbau

register_block_type( $name:String, $args:Array );

Der erste Parameter ist der Name des Blocks, i.d.R. besteht der Name aus textdomain/block-name.

// Den Block registrieren und die Handles für das Editor-Script und CSS übergeben. 
register_block_type( 'jscolorblock/color-block', array(
	'editor_script' => 'jscolorblock-color-block',
	'style' => 'jscolorblock-color-block-styles',
) );

Block-Namen können nur aus Kleinbuchstaben und Bindestrichen bestehen und müssen mit einem Buchstaben anfangen.

Der zweite Parameter übergibt zusätzliche Argumente in einem Array von Key und Wert:
Das Javascript wird mit editor_script übergeben, die CSS-Datei mit style.

Ein weiterer Key wäre editor_style, um eine CSS einzubinden und render_callback für dynamische Blöcke, wenn PHP den Block rendert.

Das vollständige PHP-Script

add_action('init', 'jscolorblock_register_block_assets');
 
function jscolorblock_register_block_assets() {
    // Pfad zur Javascript-Datei 
    $block_path = '/color-block.js';
    // Javascript des Blocks registrieren 
    wp_register_script(
        'jscolorblock-color-block',
        plugins_url( $block_path , __FILE__ ),
        [ 'wp-i18n', 'wp-element', 'wp-blocks', 'wp-components', 'wp-editor' ],
        filemtime( plugin_dir_path( $block_path , __FILE__ ) )
    );
 
    // Pfad zur CSS-Datei
    $style_path = '/color-block.css';
    wp_register_style(
        'jscolorblock-color-block-styles',
        plugins_url( $style_path , __FILE__ ),
        [],
        filemtime( plugin_dir_path( $style_path , __FILE__ ) )
    );
 
    // Block registrieren und die Handles für das Script und die CSS-Datei übergeben.
    register_block_type( 'jscolorblock/color-block', array(
        'editor_script' => 'jscolorblock-color-block',
        'style' => 'jscolorblock-color-block-styles',
    ) );
}

Das Javascript Block-Script

Da das PHP-Plugin-Script Abhängigkeiten aufgeführt hat, müssen diese Abhängigkeiten über das globale wp-Objekt zugegriffen werden, das von WordPress zum Windows-Objekt hinzufügt.

So ist z.B. registerBlockType ein Teil der wp-blocks-Library und darum verfügbar unter wp.blocks.registerBlockType.

wp.blocks.registerBlockType( name:String, typeDefinition:Object );

registerBlockType hat zwei Argumente:

  1. name ist ein String mit dem Block-Namen gefolgt von der der Block-Namen-Konvention „uniquenamespace/block-name“
  2. typeDefinition ist ein Objekt mit der Block-Konfiguration

Ein Block braucht bestimmte Eigenschaften, damit er registriert werden kann. Diese Eigenschaften werden in einem Konfigurations-Objekt als zweiter Parameter an registerBlockType übergeben.

Diese Eigenschaft sind

title
String (*required)
description
String
category
String (*required)
icon
string | WPElement | Function | Object
keywords
Array
styles
Array
attributes
Object
transforms
Array
parent
String
supports
Object
edit
WPElement (*required)
save
WPElement (*required)

Gutenberg-Blöcke bestehen aus zwei Elementen – auf der einen Seite die Gutenberg-Ansicht des Editors und auf der anderen Seite der Inhalt, der als post_content in der Datenbank gespeichert wird.

Diese beiden Komponenten kommunizieren miteinander und teilen sich Daten über Attribute auf einer Abstraktionsebene über dem REACT-State. Alle Eigenschaften dieses Objekts werden entweder in HTML-Kommentaren über dem Block oder im Block-Markup gespeichert.

WordPress übergibt ein Objekt mit den Attributen (und anderen nützlichen Eigenschaften wie eine Funktion zum Updaten der Attribut-Werte) an die edit und save-Funktionen des Javascripts.

edit: function (props) {
}

Innerhalb der edit-Funktion kann auf Attribute mit attributeName werden:

props.attributes.attributeName // Update von Attribut-Werten
isSelected: Boolean // Block momentan aktiviert
className: String // Der Name, der dem Block im Frontend zugewiesen ist

Das Argument von setAttributes ist ein Objekt, das den namen des Attributs und den neuen Wert enthält. Um die Hintergrundfarbe zu ändern

attributes: {
    backgroundColor: {
        value: "#442283",
        type: "string"
    }
},
edit: function(props) {
    props.setAttributes({
        backgroundColor: "#39ab00"
    })
}

führt ein Update der Attribut-Werte in der edit-Funktion durch. Später werden die Werte als Teil von the_content mit der save-Funktion gespeichert.

registerBlockType

Zusätzlich zum Block-Namen wird das Options-Objekt als zweiter Parameter übergeben, und zwar mit

title
wird angezeigt, wenn der Block im Editor aktiviert wird
icon
die einfachste Variante ist der Name eines Icons aus den WordPress Dashicons, ohne das führende dashicon. Allerdings kann auch SVG direkt für ein eigenes Icon verwendet werden.
category
common, formatting, layout, widgets, embed. Zusätzlich können eigene Kategorien erzeugt werden
attributes
Die Attribute des Color Blocks sind der Inhalt, Textfarbe und Hintergrundfarbe.
wp.blocks.registerBlockType( 'jsforwp/callout-block', {
	title: 'Color Block',
	icon: 'art',
	category: 'common',
	attributes: {
		content: {
			source: 'html',
			selector: 'h2',
		},
		backgroundColor: {
			type: 'string',
			default: '#F1EFBA',
		},
		textColor: {
			type: 'string',
			default: '#999999',
		}
	},

Attribute

Attribute werden als Eigenschaften im attributes-Objekt gesetzt. Jede dieser Eigenschaften ist wieder ein Objekt mit einem Wert.

type
Datentyp wie string, boolean, array, …
source
Woher die Daten kommen (z.B. meta oder html). Wird als Kommentar gespeichert, wenn das Attribute leer bleibt
selector
Ein CSS-Selektor, der angibt, woher der Block die Daten bekommt (wird nur gebraucht, wenn source html ist)
meta
Name des Meta-Werts, nur wenn der Block als Meta gespeichert wird
default
Ein Default, Vorgabewert

Die Gutenberg-Erfahrung

Als „Erfahrung“ bezeichnet Gutenberg das Look & Feel des Editors – eine völlig neue Erfahrung nach all den Jahren der Editoren wie TinyMCE.

WordPress enthält eine Vielzahl von Komponenten, die direkt benutzt werden können.

WP-Storybook

WordPress Block Editor Component Reference

Dazu noch ein Wort zu den edit- und save-Funktionen: Nur ein Element kann zurückgegeben werden. Wenn mehrere Elemente zurückgegeben werden sollen, müssen sie in ein Elemente gepackt werden.

(Fragment im wp-Element-Paket)

createElement

Das wp-element-Paket ist im Grunde genommen REACT gebündelt in WordPress. wp.element.createElement ist dasselbe wie React.createElement von REACT.

createElement nimmt den Element-Typ, der erzeugt werden soll – ein Objekt mit den Eigenschaften und Einstellungen.

wp.element.createElement( type, props, children...  )

Gutenberg Block mit RichText

Der Inhalt des Blocks wird als RichText-Komponente angelegt, direkt aus dem wp-Editor-Paket. RichText hat eine Reihe von Argumenten, die im zweiten Parameter der createElement-Funktion übergeben werden können.
Jetzt soll der Inhalt in einem h2-Element sitzen, also wird als tagName der Wert h2 übergeben. Weitere Element, die hier eingesetzt werden können, sind z.B.:

className, value, style, onChange …

Block-Editor Handbuch wordPress / rich-text

Das Script für die Gutenberg-Erfahrung des Color Block sieht dann wie folgt aus

edit: function(props) {

	wp.element.createElement( 
		wp.editor.RichText, {
			tagName: 'h2',
			className: props.className,
			value: props.attributes.content,
			style: {
				backgroundColor: props.attributes.backgroundColor,
				color: props.attributes.textColor
			},
			onChange: function( newContent ) {
				props.setAttributes( { content: newContent } );
			}
		} 
	)
	…
}

save-Funktion

Die Elemente, die in der save-Funktion zurückgegeben werden, werden in HTML-Elemente umgewandelt und dann in der Datenbank gespeichert.

save: function( props ) {
	return wp.element.createElement( wp.editor.RichText.Content, {
		tagName: 'h2', 
		value: props.attributes.content,
		style: {
			backgroundColor: props.attributes.backgroundColor,
			color: props.attributes.textColor
		},        
	} );
}

Color Block als Plugin installieren

An dieser Stelle sollte das Plugin bereits funktionieren. In den Plugins-Ordner laden und aktivieren.

Block Sidebar mit InspectorControls für die Block-Einstellungen

InspectorControls werden zusammen mit dem RichText-Element als ein Fragment-Element gepackt.

edit: function( props ) {
    return wp.element.createElement( 
        wp.element.Fragment, 
        null, 
        wp.element.createElement(
            wp.editor.InspectorControls, 
            null,
            null
        ), 
        wp.element.createElement( 
            wp.editor.RichText, 
            {
                tagName: 'h2',
                className: props.className,
                value: props.attributes.content,
                style: {
                    backgroundColor: props.attributes.backgroundColor,
                    color: props.attributes.textColor
                },
                onChange: function( newContent ) {
                    props.setAttributes( { content: newContent } );
                }
            } 
        )
    )
}

Hier kann PanelColorSettings als ein Child-Element der InspectorControls eingesetzt werden. Diese Komponente erzeugt den Color Picker.

wp.element.createElement(
    wp.editor.InspectorControls, 
    null,
    wp.element.createElement(
        wp.editor.PanelColorSettings, 
        {
            ...
        }
    )
),

Den PanelColorSettings werden ein Titel und ein Array mit den Farbeinstellungen übergeben. Jede Farbeinstellung ist ein Objekt mit den Eigenschaften label, value und onChange.

{
    label: wp.i18n.__("Text Color", "jsforwp"),
    value: props.attributes.textColor,
    onChange: function( newColor ) {
        props.setAttributes({ textColor: newColor });
    }
}

Damit wären alle Zutaten für den Color Block zusammengetragen. Das komplette Javascript sieht so aus:

wp.blocks.registerBlockType( 'jscolorblock/color-block', {
 
    title: 'Color Block',
    icon: 'art',
    category: 'common',
    attributes: {
        content: {
            source: 'html',
            selector: 'h2',
        },
        backgroundColor: {
            type: 'string',
            default: '#F1EFBA',
        },
        textColor: {
            type: 'string',
            default: '#999999',
        }
    },
 
    edit: function( props ) {
        return wp.element.createElement( 
            wp.element.Fragment, 
            null, 
            wp.element.createElement(
                wp.editor.InspectorControls, 
                null,
                wp.element.createElement(
                    wp.editor.PanelColorSettings, {
                        title: wp.i18n.__("Color Settings", "jscolorblock"),
                        colorSettings: [
                            {
                                label: wp.i18n.__("Background Color", "jscolorblock"),
                                value: props.attributes.backgroundColor,
                                onChange: function( newBackgroundColor ) {
                                    props.setAttributes({ backgroundColor: newBackgroundColor });
                                }
                            },
                            {
                                label: wp.i18n.__("Text Color", "jscolorblock"),
                                value: props.attributes.textColor,
                                onChange: function( newColor ) {
                                    props.setAttributes({ textColor: newColor });
                                }
                            }
                        ]
                    }
                )
            ),
            wp.element.createElement( 
                wp.editor.RichText, {
                    tagName: 'h2',
                    className: props.className,
                    value: props.attributes.content,
                    style: {
                        backgroundColor: props.attributes.backgroundColor,
                        color: props.attributes.textColor
                    },
                    onChange: function( newContent ) {
                        props.setAttributes( { content: newContent } );
                    }
                } 
            ) 
        );
    },
 
    save: function( props ) {
        return wp.element.createElement( wp.editor.RichText.Content, {
            tagName: 'h2', 
            value: props.attributes.content,
            style: {
                backgroundColor: props.attributes.backgroundColor,
                color: props.attributes.textColor
            },        
        } );
    }
} );

Noch die CSS-Datei für Color Block

Gutenberg nutzt den Namen, der in der registerBlockType-Funktion übergeben wurde, und erzeugt daraus eine CSS-Klasse. Die Klasse unterliegt den folgenden Namenskonventionen:

wp-block-namespace-block-name

also für dieses Beispiel

wp-block-jscolorblock-color-block

In die CSS-Datei kommt dann noch

.wp-block-jscolorblock-color-block {
    padding: 20px;
    font-weight:300;
}

Quellen: WordPress Package Reference
Gutenberg Block Tutorial
InspectorControls – How to Add Settings to Custom Gutenberg Blocks