Eigenen WordPress Block entwickeln – Teil 3: WordPress Block mit registerBlockType registrieren

In dieser Artikelreihe erkläre ich, wie du von Grund auf deinen eigenen WordPress Block entwickeln kannst. Im dritten Teil sehen wir uns die Funktion registerBlockType an, mit der du deinen WordPress Block registrieren und im Gutenberg Editor hinzufügen kannst.

Zum Start der Serie und ersten Teil geht es hier.

Dateien für neuen WordPress Block anlegen

Nachdem wir im zweiten Teil unser Plugin mit dem Create Guten Block Toolkit erstellt haben, können wir nun mit der Entwicklung unseres Beispiels – einem Image Card Block – starten.

Wir legen dazu einen neuen Ordner /image-card im Source-Verzeichnis an. Darin erstellen wir zwei neue und leere Dateien: index.js und style.css. Wir fangen praktisch bei Null an, weshalb du den bestehenden Example-Block des CGB-Toolkits löschen kannst.

Das src-Verzeichnis sollte nun folgende Struktur aufweisen:

├── src
|   ├── image-card
|   |   ├── index.js
|   |   └── style.scss
|   |
|   ├── blocks.js
|   ├── common.scss
|   └── init.php

Anschließend öffnen wir die Datei /src/blocks.js und importieren unseren neuen Block:

import './image-card/index.js';

Damit wird die neu erstellte index.js von Webpack eingelesen und wir können dort unseren neuen WordPress Block registrieren und entwickeln. Falls dein Plugin weitere Blocks enthalten soll, kannst du im src-Verzeichnis auch einfach weitere Ordner für zusätzliche Blocks erstellen.

Die Funktion registerBlockType im Überblick

Jeder Block wird mit der Funktion registerBlockType() im Editor registriert. Die Funktion wird uns vom Package wp-blocks bereitgestellt und nimmt zwei Parameter entgegen:

  • name string: Block Name.
  • settings Object: Block Settings.
registerBlockType( 'my-plugin/block-name', {} );

Als Erstes muss ein eindeutiger String übergeben werden, welcher den Block identifiziert. Dazu wird der Name üblicherweise mit namespace/block-name strukturiert und als Namespace der Slug des WordPress Plugins verwendet. In unserem Fall folglich themecoder-block/image-card.

Wesentlich interessanter ist das Configuration bzw. Settings Object, welches als zweites Argument übergeben wird. In diesem Objekt definieren wir alle Eigenschaften und Funktionen, welche unseren Block auszeichnen und funktionsfähig machen.

Die wichtigsten Properties für die Block Settings sind:

  • title string: Der angezeigte Name des Blocks im Editor.
  • category string: Zu welcher Kategorie im Block Inserter gehört der Block.
  • attributes Object: Deklarierung aller Daten bzw. Variablen des Blocks.
  • edit function: Beschreibt, wie der Block im Editor gerendert und dargestellt wird.
  • save function: Beschreibt, wie der Block im Frontend dargestellt wird.

Für das Settings Object bestehen natürlich noch eine Menge anderer Properties, mit denen wir uns noch eingehender beschäftigen werden.

Wichtig an dieser Stelle ist zu wissen, dass mit dem Settings Object unser kompletter Block definiert wird. Das Objekt enthält alle Eigenschaften, Attribute und Funktionen des Blocks und wird als zweiter Parameter an registerBlockType() übergeben.

Image Card WordPress Block registrieren

Genug der Theorie. Es ist an der Zeit, etwas Code zu schreiben und unseren Block zu erstellen.

Du kannst dazu folgenden Code in der Datei /src/image-card/index.js einfügen:

/**
 * Register block
 */
wp.blocks.registerBlockType( 'themecoder-block/image-card',
	{
		title: wp.i18n.__( 'Image Card', 'themecoder-block' ),

		category: 'layout',

		edit() {
			return (
				<div>Block Content im Editor</div>
			);
		},

		save() {
			return (
				<div>Block Content im Frontend</div>
			);
		},
	}
);

Wir registrieren unseren Block mit wp.blocks.registerBlockType() und definieren in unseren Settings einen Titel, eine Kategorie und die Edit- und Save-Funktionen. Diese geben kein HTML, sondern JSX zurück, weshalb hier keine Anführungszeichen für Strings notwendig sind.

Und das wars auch schon.

Du solltest nun im Block Inserter den Image Card Block finden und einfügen können:

Block Inserter

Tipp: Stelle sicher, dass du Webpack mit npm start angestoßen hast, falls der Block fehlt.

Die WordPress Packages im Gutenberg Editor

WordPress Core stellt uns seit Version 5.0 eine Reihe von Packages zur Entwicklung von Blocks zur Verfügung. Diese sind inzwischen auch als NPM-Packages verfügbar, z.B. @wordpress/blocks.

Für die Entwicklung von Blocks müssen wir diese aber nicht als externe Node-Module installieren. Der Gutenberg Editor stellt uns nämlich freundlicherweise (fast) alle Packages in der globalen Variable wp bereit, welche als riesiges Objekt alle Komponenten und Funktionen enthält.

Die wichtigsten Packages für unsere Zwecke sind:

  • wp.element – Abstraction Layer von WordPress für React und ReactDOM.
  • wp.blocks – Hauptsächlich Funktionen zum Erstellen und Manipulieren von Blocks.
  • wp.components – Allgemeine Komponenten für häufig vorkommende UI-Elemente.
  • wp.editor – Spezifischere Komponenten für UI-Elemente im Gutenberg Editor.
  • wp.i18n – Enthält alle Lokalisierungsfunktionen für die Übersetzung von Textstrings.
  • wp.data – Funktionen, um mit den Redux Data Stores von WordPress zu interagieren.

Das Tippen des kompletten Pfads zu einer Funktion (z.B. wp.blocks.registerBlockType) wäre auf Dauer etwas mühsam, weshalb wir uns ein ES6-Feature names Destructuring zu Nutze machen. Mit dem Object Destructuring der WP Packages extrahieren wir nur die gerade benötigten Funktionen aus dem globalen wp-Objekt und machen diese als Variablen zugänglich.

Wir können unseren obigen Code dementsprechend etwas anpassen und klarer gestalten:

/**
 * WordPress dependencies
 */
const { registerBlockType } = wp.blocks;
const { __ } = wp.i18n;

/**
 * Register block
 */
registerBlockType( 'themecoder-block/image-card',
	{
		title: __( 'Image Card', 'themecoder-block' ),

		category: 'layout',

		edit() {
			return (
				<div>Block Content im Editor</div>
			);
		},

		save() {
			return (
				<div>Block Content im Frontend</div>
			);
		},
	}
);

Destructuring begegnet uns sehr häufig bei der Entwicklung mit React und Gutenberg Blocks. Falls du mit modernen JavaScript noch nicht vertraut bist, empfehle ich, den Begriff zu googeln und einige Tutorials zu lesen, beispielsweise dem Destructuring Guide von codeburst.

HTML-Markup für Image Card Block erstellen

Nachdem wir unseren Block im Editor registriert haben, können wir nun das HTML-Grundgerüst für unsere Image Card erstellen. Der Block soll später Bild und Text in zwei Spalten anzeigen, weshalb wir einige div-Elemente für diese Struktur erstellen.

Dabei solltest du beachten, dass wir hier weiterhin JSX und nicht HTML schreiben, was zu einigen Unterschieden führt. Der Begriff class ist in JavaScript registriert für Klassen, weshalb in JSX auf className zurückgegriffen wird, um das Klassen-Attribut in HTML-Elementen auszuweisen.

Wir beginnen mit der Änderung der Save-Funktion unseres WordPress Blocks:

save() {
	return (
		<div>
			<div className="tc-columns">

				<div className="tc-image">

				</div>

				<div className="tc-card">

					<h2>Titel des Blocks</h2>
					<p>Beschreibung des Blocks.</p>

				</div>

			</div>
		</div>
	);
},

Das erste Div-Element ist unser Block-Wrapper. Für die Save-Funktion wird automatisch die CSS-Klasse des Blocks eingefügt, sodass wir als Entwickler darauf verzichten können. Die Klasse wird aus dem Prefix wp-block, dem Namespace und Name des Blocks generiert. In unserem Fall lautet der vollständige Name also wp-block-themecoder-block-image-card.

In der Edit-Funktion für das Rendern des Blocks im Editor wird die CSS Klasse nicht automatisch hinzugefügt. Aus diesem Grund fügen wir diese manuell ein. Wir bekommen die Klasse mit der Variable className aus dem props-Argument. Wir nutzen dafür wieder Destructuring.

edit( props ) {
	const { className } = props;

	return (
		<div className={ className }>
			<div className="tc-columns">

				<div className="tc-image">

				</div>

				<div className="tc-card">

					<h2>Titel des Blocks</h2>
					<p>Beschreibung des Blocks.</p>

				</div>

			</div>
		</div>
	);
},

Wie in Teil 1 bereits kurz erwähnt, setzt React auf Komponenten, welche ineinander verschachtelt werden. Dabei können Input-Variablen von der Parent Component zu Child Komponenten in Form des props-Arguments übergeben werden. Props steht für Properties und ist ein Objekt, dass beliebig viele Variablen enthalten kann.

Auch WordPress Blocks weisen ein props-Objekt auf, welches als Parameter für die Save- und Edit-Funktion eines Blocks zur Verfügung steht. Du kannst zum Test in der Edit-Funktion die props mit console.log( props ) in der Browser-Konsole ausgeben lassen, um einen Überblick über alle props des Blocks zu erhalten. Du solltest ein Objekt mit ähnlichen Variablen erhalten:

props: {
	attributes: {},
	className: "wp-block-themecoder-block-image-card",
	clientId: "6b0366da-11af-45f2-9af0-4080415e5eed",
	isSelected: false,
	name: "themecoder-block/image-card",
	[...]
}

Für die Entwicklung von Custom Blocks werden wir später sehr häufig die Property attributes benötigen, in der alle Daten und Optionen des Blocks gespeichert werden. Momentan ist das Objekt noch leer, weil wir noch keine Block Attribute definiert haben.

Styling für WordPress Block hinzufügen

Als letzten Schritt für heute fügen wir nun noch etwas Styling für unseren WordPress Block hinzu. Dazu importieren wir erst einmal unsere style.scss, und zwar ausgehend von der index.js unseres Blocks. Du kannst den Code über der Funktion registerBlockType() einfügen:

/**
 * Internal dependencies
 */
import './style.scss';

In der style.scss können wir unseren WordPress Block nun stylen. Für unsere Zwecke reichen ein paar Abstände und etwas Schlagschatten. Das zweispaltige Layout realisieren wir mit Flexbox.

.wp-block-themecoder-block-image-card {
	margin-bottom: 1.5em;
	box-shadow: 0 0 10px #ccc;

	.tc-columns {
		display: flex;

		.tc-image {
			width: 50%;
			background: #eee;
		}

		.tc-card {
			width: 50%;
			padding: 4em 2em;

			h2 {
				margin-top: 0;
			}

			p {
				margin-bottom: 0;
			}
		}
	}
}

Damit es überschaubar für das Tutorial bleibt, verzichten wir auf Responsive Design, d.h. der Block bleibt auch auf kleineren Screens zweispaltig.

Ergebnis und Ausblick auf Teil 4

Als Ergebnis solltest du nun diesen Block erhalten, der natürlich noch vollkommen statisch ist.

Image Card Block Teil 3

Du findest den kompletten Code unseres WordPress Blocks auf Github und kannst das Repo auch von dort klonen und installieren. Ich werde für jeden Teil des Tutorials den aktuellen Stand als neuen Block veröffentlichen, sodass du alle Schritte jederzeit nachverfolgen kannst.

Repo: https://github.com/Netzberufler/themecoder-block

Im nächsten Teil werden wir mit der RichText-Komponente Eingabefelder hinzufügen, um den  Titel und die Beschreibung des Blocks editierbar zu machen. Danach geht es weiter mit Medien-Upload sowie Toolbar- und Sidebar-Optionen für den Block.

Überblick über alle Beiträge dieser Serie