Snap je nog steeds niks van Gutenberg? Of hoor je bij de groep die heilig gelooft in de mogelijkheden van de blok-editor en willen ontdekken hoe ver ze met hun creativiteit kunnen gaan met behulp van de blok-editor?

In welke categorie gebruikers je ook valt, Gutenberg gaat niet meer weg en dit artikel geeft je een diepgaand overzicht van wat er achter de schermen van de WordPress blok-editor gebeurt. Maar dat is nog niet alles!

Na onze vorige tutorial waarin we een algemene inleiding gaven over het ontwikkelen van blokken in Gutenberg, gaat dit artikel verder dan de basics en introduceert meer geavanceerde bloktypes. Deze blokken worden dynamische blokken genoemd.

Vandaag leer je wat dynamische blokken zijn, hoe ze werken, en alles wat je moet weten om vanuit het niets dynamische blokken te maken.

Om mee te beginnen, wat zijn Gutenberg dynamische blokken, en wat zijn de belangrijkste verschillen tussen statische en dynamische blokken?

Wat zijn dynamische blokken? Een voorbeeld

Waar bij statische blokken de inhoud handmatig door de gebruiker wordt toegevoegd tijdens het bewerken van een bericht of pagina, wordt bij dynamische blokken de inhoud bij het laden van de pagina geladen en meteen verwerkt. Met dynamische blokken wordt de blokinhoud uit de database opgepikt en weergegeven zoals hij is of het resultaat van datamanipulatie.

Laten we dat met een voorbeeld uitleggen. Stel dat je een groep geneste blokken wilt maken die de details van de auteur van een artikel tonen met een selectie van de laatste berichten van dezelfde auteur.

Een Group block inclusief Post Author en Lastest Posts
Een Group block inclusief Post Author en Lastest Posts

Als Gutenberg gebruiker zou je de volgende blokken kunnen gebruiken:

  • Het Heading kernblok
  • Het core blok Post Author
  • Het core blok Latest Posts

Je zou ook een groep kunnen maken met daarin die blokken en de groep toevoegen aan herbruikbare blokken (voor toekomstig gebruik).

Een Groups block toevoegen aan herbruikbare blokken
Een Groups block toevoegen aan herbruikbare blokken

Dit is nogal rechttoe rechtaan, nietwaar? Je kunt een dynamisch blok maken en het in een handomdraai aan je berichten en pagina’s toevoegen.

Vanaf WordPress 5.9 biedt de blok-editor meer dan 90 verschillende blokken, en de kans is groot dat je het blok dat bij je past gewoon standaard inbegrepen zit. En, als je er meer nodig hebt, zoek dan eens in de WordPress plugin directory en je vindt een heleboel gratis plugins die extra blokken bieden.

Maar wat als je een WordPress ontwikkelaar bent – of als je een carrière als WordPress ontwikkelaar plant? Misschien heb je heel specifieke behoeften en kun je het blok dat je zoekt niet vinden, of wil je gewoon nieuwe professionele vaardigheden opdoen. In zulke situaties wil je misschien leren hoe je zelf dynamische blokken kunt maken.

Dynamische blokken van Gutenberg vanuit het perspectief van een ontwikkelaar

Dynamische blokken hebben twee belangrijke gebruikssituaties.

Het eerste gebruik is wanneer je de inhoud van een blok moet bijwerken terwijl de pagina waarop het blok staat nog niet is bijgewerkt. Dit gebeurt bijvoorbeeld als het blok een lijst van de nieuwste berichten of reacties bevat, en in het algemeen telkens als de inhoud van het blok dynamisch gegenereerd wordt met gegevens die uit de database opgehaald worden.

Toevoegen van een Query Loop blok
Toevoegen van een Query Loop blok

Het tweede gebruiksgeval is wanneer een update van de blokcode onmiddellijk aan de frontend getoond moet worden. Door een dynamisch blok te gebruiken in plaats van een statisch blok worden de veranderingen onmiddellijk toegepast op alle instanties van het blok.

Zou je daarentegen de door een statisch blok geproduceerde HTML veranderen, dan krijgt de gebruiker een invalidation dialoog te zien tot elke losse instantie van de vorige versie van het blok verwijderd is en vervangen door de nieuwe versie, of tot je de oude versies als deprecated markeert (zie ook Deprecation en Block Validation, Deprecation en Migration Experience).

Onverwachte of ongeldige inhoud.
Onverwachte of ongeldige inhoud.

Dat gezegd hebbende, zijn er een paar begrippen die je moet begrijpen voor je kunt beginnen met het bouwen van dynamische blokken.

Application state en data stores

Gutenberg is een React SPA applicatie, en alles in Gutenberg is een React component. Berichttitel, headers, alinea’s, afbeeldingen en elk blok met HTML content in de editor is een React component, net als de controls van de zijbalk en toolbar van blokken.

In ons vorige artikel gebruikten we alleen eigenschappen om gegevens op te slaan. In dit artikel gaan we een stap verder door het concept toestand te introduceren.

Eenvoudig gezegd is het state object een plain JavaScript object dat gebruikt wordt om informatie over een component te bevatten. De state van het object kan in de loop van de tijd veranderen, en telkens als die verandert, wordt het object opnieuw opgebouwd.

Net als het state object zijn properties plain JavaScript objecten die gebruikt worden om informatie over de component te bewaren. Maar er is een belangrijk verschil tussen props en state:

props worden aan de component doorgegeven (vergelijkbaar met functieparameters), terwijl state binnen de component beheerd wordt (vergelijkbaar met variabelen die binnen een functie gedeclareerd worden).

Je kunt de state zien als een momentopname van gegevens die op een bepaald moment genomen worden en die een toepassing opslaat om het gedrag van een component te regelen. Bijvoorbeeld, als de instellingenzijbalk van de blok-editor geopend is, wordt ergens in hetstate object een stukje informatie opgeslagen.

Als de informatie binnen een enkele component gedeeld wordt, noemen we dat local state. Als de informatie gedeeld wordt over componenten binnen een toepassing, noemen we het Application State.

Application State is nauw verwant met het concept van store. Volgens de Redux docs:

Een store bevat de hele state tree van je toepassing. De enige manier om de toestand erin te veranderen is er een actie

op te dispatchen.
Redux slaat dus de state van een toepassing op in een enkele onveranderlijke object tree (namelijk een store). De object tree kan alleen veranderd worden door een nieuw object te maken met behulp van acties en reducers.

In WordPress worden stores beheerd door de WordPress data module.

Modulariteit, packages, en data stores in Gutenberg

De Gutenberg repository is vanaf de grond opgebouwd via verschillende herbruikbare en onafhankelijke modules die, samengevoegd, de bewerkingsinterface bouwen. Deze modules worden ook wel packages genoemd.

De officiële documentatie noemt twee verschillende soorten packages:

  • Production packages vormen de productiecode die in de browser draait. Er zijn twee soorten production packages in WordPress:
    • Packages met stylesheets zorgen voor stylesheets om goed te kunnen functioneren.
    • Packages met data stores definiëren data stores om hun state te handlen. Packages met data stores kunnen door plugins en externe thema’s gebruikt worden om gegevens op te halen en te manipuleren.
  • Development packages worden gebruikt in de ontwikkelingsmodus. Die pakketten bevatten tools voor linting, testen, bouwen, enz.

Hier zijn we vooral geïnteresseerd in packages met data stores, die gebruikt worden om gegevens op te halen en te manipuleren.

De WordPress data store

De WordPress data module is gebouwd op Redux en deelt de drie kernprincipes van Redux, zij het met enkele belangrijke verschillen.

De officiële documentatie geeft de volgende definitie:

De data module van WordPress dient als hub om de state van de toepassing te beheren, zowel voor plugins als voor WordPress zelf, en biedt tools om gegevens te beheren binnen en tussen verschillende modules. Ze is ontworpen als een modulair patroon voor het organiseren en delen van gegevens: eenvoudig genoeg om te voldoen aan de behoeften van een kleine plugin, en tegelijk schaalbaar om te voldoen aan de eisen van een complexe single-page applicatie.

Standaard registreert Gutenberg verschillende data stores binnen de toestand van de applicatie. Elk van deze data stores heeft een specifieke naam en doel:

Via deze stores heb je toegang tot een heleboel gegevens:

  1. Gegevens die te maken hebben met het huidige bericht, zoals de titel van het bericht, uittreksel, categorieën en tags, blokken, enz.
  2. Gegevens die te maken hebben met de gebruikersinterface, d.w.z. of een toggle aan of uit staat.
  3. Gegevens die te maken hebben met de hele WordPress installatie, zoals geregistreerde taxonomieën, posttypes, blogtitel, auteurs, enz.

Deze data stores leven in het globale wp object. Om toegang te krijgen tot de state van een store, gebruik je de functie select.

Om te zien hoe dat werkt, maak je een nieuw bericht of pagina en start je de inspector van je browser. Zoek de console en typ de volgende regel code in:

wp.data.select("core")

Het resultaat is een object met daarin een lijst van functies die je kunt gebruiken om gegevens uit decore data store. Deze functies heten selectors en fungeren als interfaces om toegang te krijgen tot state values.

Het Core WordPress data store object
Het Core WordPress data store object

De WordPress data store bevat informatie over WordPress in het algemeen en selectors zijn de manier waarop je die informatie krijgt. Bijvoorbeeld, getCurrentUser() geeft gegevens voor de huidige gebruiker:

wp.data.select("core").getCurrentUser()
Inspecteren van getCurrentUser antwoord
Inspecteren van getCurrentUser antwoord

Een andere selector die je kunt gebruiken om gebruikersgegevens uit de data store op te halen is getUsers() :

wp.data.select("core").getUsers()

De volgende afbeelding toont het response object:

Inspecteren van getUsers antwoord
Inspecteren van getUsers antwoord

Om gegevens voor een enkele gebruiker te krijgen, kun je gewoon de volgende regel typen:

wp.data.select("core").getUsers()[0]

Met dezelfde selector kun je ook sitegebruikers ophalen die de rol author zijn toegekend:

wp.data.select( 'core' ).getUsers({ who: 'authors' })

Je kunt ook geregistreerde taxonomieën ophalen:

wp.data.select("core").getTaxonomies()
Inspecteren van getTaxonomies antwoord.
Inspecteren van getTaxonomies antwoord.

Een lijst van de geregistreerde post types:

wp.data.select("core").getPostTypes()

Of een lijst van plugins:

wp.data.select("core").getPlugins()

Laten we nu proberen een andere data store te openen. Om dat te doen gebruik je nog steeds de functie select, maar je geeft een andere namespace. Laten we het volgende proberen:

wp.data.select("core/edit-post")

Nu krijg je het volgende response object.

Toegang tot de UI-gegevens van de editor
Toegang tot de UI-gegevens van de editor

Als je wilt weten of de instellingenzijbalk open is of niet, zou je de isEditorSidebarOpened selector gebruiken:

wp.data.select("core/edit-post").isEditorSidebarOpened()

Deze functie geeft true terug als de zijbalk open is:

De zijbalk is open.
De zijbalk is open.

Zo krijg je toegang tot berichtdata

Je zou nu een basisbegrip moeten hebben van hoe je bij data kan komen. Nu gaan we dieper in op een specifieke selector, de functiegetEntityRecords, die toegang geeft tot de berichtdata.

Klik in de blok-editor met rechts en kies Inspect. Kopieer en plak in het tabblad Console de volgende regel:

wp.data.select("core").getEntityRecords('postType', 'post')

Dit stuurt een verzoek naar de Rest API en geeft een array van records terug die overeenkomen met de laatst gepubliceerde blogberichten.

getEntityRecords geeft een lijst van berichten terug.
getEntityRecords geeft een lijst van berichten terug.

getEntityRecords accepteert drie parameters:

  • kind string: Soort entiteit (i.e. postType).
  • name string: Naam van de entiteit (i.e. post).
  • query object: Optionele terms query (i.e. {author: 0}).

Je kunt specifiekere verzoeken bouwen met een object van argumenten.

Je kunt bijvoorbeeld beslissen dat het antwoord alleen berichten uit een bepaalde categorie mag bevatten:

wp.data.select("core").getEntityRecords('postType', 'post', {categories: 3})

Je kunt ook alleen artikelen van een bepaalde auteur opvragen:

wp.data.select("core").getEntityRecords('postType', 'post', {author: 2})

Als je op een van de door getEntityRecords geretourneerde records klikt, krijg je een lijst van properties voor het geselecteerde record:

Een voorbeeld van een API verzoek met getEntityRecords.
Een voorbeeld van een API verzoek met getEntityRecords.

Als je wilt dat het antwoord ook de uitgelichte afbeelding bevat, moet je een extra argument aan je vorige verzoek toevoegen:

wp.data.select("core").getEntityRecords('postType', 'post', {author: 2, _embed: true})
Details van de uitgelichte afbeelding in getEntityRecords antwoord.
Details van de uitgelichte afbeelding in getEntityRecords antwoord.

Nu zou je beter moeten begrijpen hoe je de WordPress data store kunt gebruiken en berichtinformatie kunt ophalen. Voor meer info over de getEntityRecords selector, zie Data opvragen in Gutenberg met getEntityRecords.

Zo maak je een dynamisch blok: een voorbeeldproject

Na onze lange theoretische inleiding kunnen we overgaan tot de praktijk en een dynamisch blok maken met de tools die we in onze vorige tutorial over blokontwikkeling introduceerden.

In dat artikel bespraken we:

  1. Hoe je een WordPress ontwikkelomgeving opzet
  2. Wat een bloksteiger is
  3. Hoe je een statisch Gutenberg blok bouwt

Daarom gaan we in dit artikel niet dieper in op die onderwerpen, maar raadpleeg gerust onze vorige gids voor aanvullende informatie, of gewoon voor een opfrisser.

Een JavaScript ontwikkelomgeving opzetten

Laten we beginnen met het opzetten van een JavaScript ontwikkelomgeving.

Installeer of update Node.js

Installeer of update eerst Node.js. Als je klaar bent, start je je opdrachtregelprogramma en voer je het volgende commando uit:

node -v

Je zou je node versie moeten zien.

Stel je ontwikkelomgeving in

Vervolgens heb je een ontwikkelomgeving voor WordPress nodig. Voor onze voorbeelden gebruikten we DevKinsta, onze gratis WordPress ontwikkelingstool waarmee je in een handomdraai een lokale WordPress website kunt starten.

Een aangepaste site maken in DevKinsta
Een aangepaste site maken in DevKinsta

Maar je bent nog steeds vrij om een WordPress lokale ontwikkelomgeving te kiezen die je bevalt, zoals MAMP of XAMPP, of zelfs de officiële wp-env oplossing.

Als je DevKinsta gebruikt, klik je op New WordPress Site of op Custom Site, vul de formuliervelden in en druk op Create site.

Het installatieproces duurt een minuut of twee. Als het klaar is, start je je lokale WordPress ontwikkelingswebsite.

Site Info scherm in DevKinsta.
Site Info scherm in DevKinsta.

Stel je blok-plugin in

Wat je nu nodig hebt is een starterblokplugin. Om al het gedoe van een handmatige configuratie te vermijden, bracht het core developer team van WordPress de @wordpress/create-block tool uit, dat deofficiële zero-configuratie tool is voor het maken van Gutenberg blokken.

We behandelden @wordpress/create-block uitvoerig in ons vorige artikel, dus hier kunnen we meteen met de opstelling beginnen.

Navigeer in de commandoregeltool naar de map /wp-content/plugins:

Nieuwe terminal bij map in Mac OS.
Nieuwe terminal bij map in Mac OS.

Eenmaal daar voer je het volgende commando uit:

npx @wordpress/create-block

Je bent nu klaar om de @wordpress/create-block package te installeren:

Installeren van het @wordpress/create-block pakket.
Installeren van het @wordpress/create-block pakket.

Om te bevestigen typ je y en druk op Enter.

Dit genereert de PHP, SCSS, en JS bestanden van de plugin in interactieve modus.

Hieronder staan de details die we in ons voorbeeld zullen gebruiken. Voel je vrij om deze gegevens naar eigen voorkeur te veranderen:
[mededeling]

  • Block slug used for identification (also the plugin and output folder name): author-plugin
  • The internal namespace for the block name (something unique for your products): author-box
  • The display title for your block: Author box
  • The short description for your block (optional): An example block for Kinsta readers
  • The dashicon to make it easier to identify your block (optional): businessperson
  • The category name to help users browse and discover your block: widgets
  • The name of the plugin author (optional). Multiple authors may be listed using commas: je naam
  • The short name of the plugin’s license (optional): 
  • A link to the full text of the license (optional): 
  • The current version number of the plugin: 0.1.0

[/notice]
Zodra je op Enter drukt, downloadt en configureert de plugin.

Installeren van de blok-plugin.
Installeren van de blok-plugin.

Het proces kan een paar minuten duren. Als het voltooid is, zou je het volgende scherm moeten zien:

Block bootstrapped in de plugin map.
Block bootstrapped in de plugin map.

Je ziet nu een lijst van de commando’s die je kunt uitvoeren vanuit de plugin map:

  • $ npm start – Start de build voor ontwikkeling.
  • $ npm run build – Bouw de code voor productie.
  • $ npm run format – Formatteer bestanden.
  • $ npm run lint:css – Lint CSS bestanden.
  • $ npm run lint:js – Lint JavaScript bestanden.
  • $ npm run packages-update – Werk WordPress pakketten bij tot de nieuwste versie.

Ga nu naar de pluginmap met het volgende commando:

cd author-plugin

En start je ontwikkelingsbuild:

npm start

Vervolgens ga je naar het Plugins scherm in je WordPress dashboard en activeer je de Author box plugin:

De blokplugin staat in het Plugins scherm.
De blokplugin staat in het Plugins scherm.

Nu kun je controleren of de plugin goed werkt. Maak een nieuw bericht en begin met het typen van / om de quick inserter te starten:

Het blok-item in de Snelle invoegtoepassing.
Het blok-item in de Snelle invoegtoepassing.

Je vindt het Author box blok ook in de Block Inserter, onder de categorie Widgets. Selecteer het blok om het aan het editor canvas toe te voegen:

De WordPress Block Inserter
De WordPress Block Inserter

Je bent klaar. Sla nu het bericht op en bekijk een voorbeeld van de pagina om te zien of het blok correct wordt weergegeven.

De bloksteiger

We behandelden de bloksteiger al in ons vorige artikel. We geven hier dus alleen een kort overzicht van de bestanden die we voor onze voorbeelden gaan wijzigen.

De root map
De root map is waar je het hoofd PHP bestand vindt en verschillende submappen.

author-plugin.php
Standaard levert de @wordpress/create-block package het volgende PHP bestand:

/**
 * Plugin Name:       Author box
 * Description:       An example block for Kinsta readers
 * Requires at least: 5.8
 * Requires PHP:      7.0
 * Version:           0.1.0
 * Author:            Carlo
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       author-plugin
 *
 * @package           author-box
 */

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
function author_box_author_plugin_block_init() {
	register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'author_box_author_plugin_block_init' );

In de heading zie je de data die we bij de setup hebben ingevoerd.

Met statische blokken zul je meestal werken aan de JavaScript bestanden die in de src map staan. Met dynamische blokken schrijf je PHP code om de inhoud van het blok aan de front-end te tonen.

De src map
De src map is je ontwikkelingsmap. Hier vind je de volgende bestanden:

  • block.json
  • index.js
  • edit.js
  • save.js
  • editor.scss
  • style.scss

block.json
De block.json is je metadata-bestand. @wordpress/create-block genereert het volgende block.json bestand:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "author-box/author-plugin",
	"version": "0.1.0",
	"title": "Author box",
	"category": "widgets",
	"icon": "businessperson",
	"description": "An example block for Kinsta readers",
	"supports": {
		"html": false
	},
	"textdomain": "author-plugin",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

Voor meer algemene informatie over het block.json bestand, verwijs ik je naar ons vorige blogbericht.

index.js
Het index.js bestand is waar je het bloktype op de client registreert:

import { registerBlockType } from '@wordpress/blocks';

import './style.scss';

import Edit from './edit';
import save from './save';

registerBlockType('author-box/author-plugin', {
	edit: Edit,
	save,
});

edit.js
Het edit.js bestand is waar je de blok-interface opbouwt die in de editor wordt weergegeven:

import { __ } from '@wordpress/i18n';

import { useBlockProps } from '@wordpress/block-editor';

import './editor.scss';

export default function Edit() {
	return (
		<p {...useBlockProps()}>
			{__('Author box – hello from the editor!', 'author-plugin')}
		</p>
	);
}

save.js
Het save.js bestand bevat het script dat de blokinhoud bouwt om in de database te worden opgeslagen. We zullen dit bestand in deze tutorial niet gebruiken:

import { __ } from '@wordpress/i18n';

import { useBlockProps } from '@wordpress/block-editor';

export default function save() {
	return (
		<p {...useBlockProps.save()}>
			{__('Author box – hello from the saved content!', 'author-plugin')}
		</p>
	);
}

Het blok bouwen om te renderen in de editor

Open je project in Visual Studio Code of een andere code-editor waar je graag mee werkt.

Als je Visual Studio Code gebruikt, ga dan naar Terminal -> New Terminal. Dit start een terminalvenster op in de hoofdmap van je project.

Typ in de terminal (of in je favoriete opdrachtregelprogramma) het volgende commando:

npm start

Je draait nu de node omgeving in ontwikkelingsmodus.

Het blokpluginproject in Visual Studio Code.
Het blokpluginproject in Visual Studio Code.

Vanaf hier volg je twee verschillende routes. Om het blok in de editor te renderen, werk je in het edit.js bestand. Om het blok aan de frontend weer te geven, moet je PHP code schrijven in het hoofdbestand van de plugin.

Stroop nu je mouwen op want we kunnen beginnen met coderen:

Registreer het blok op de server

Eerst moet je het blok op de server registreren en de PHP code schrijven om gegevens uit de database op te halen.

In het bestand author-plugin.php moet je een tweede argument doorgeven aan de functieregister_block_type:

function author_box_author_plugin_block_init() {
	register_block_type( __DIR__ . '/build', array(
		'render_callback' => 'author_box_author_plugin_render_author_content'
	) );
}
add_action( 'init', 'author_box_author_plugin_block_init' );

Het tweede argument is een array van argumenten voor het registreren van een bloktype (zie hier de volledige lijst van beschikbare argumenten). In de code hierboven hebben we alleen render_callback meegegeven, die de callbackfunctie bepaalt die het blok op het scherm rendert.

Vervolgens declareer je de functie:

function author_box_author_plugin_render_author_content() {
	return 'Hello World!';
}

Sla het bestand op, maak een nieuw bericht of pagina, en voeg het Author Box blok toe aan het editor canvas.

De WordPress Block Inserter.
De WordPress Block Inserter.

De blok-editor toont nog steeds het startblok, want we hebben het edit.js bestand nog niet veranderd.

Maar als je nu een voorbeeld van het bericht in de frontend bekijkt, zie je dat de oorspronkelijke blokinhoud nu vervangen is door de “Hello World” string.

Omdat de HTML die op het frontend wordt weergegeven door het PHP bestand wordt gegenereerd, hoeft de save functie niets terug te geven. Laten we dus meteen naar het save.js bestand gaan en de code veranderen zoals hieronder:

export default function save() {
	return null;
}

Definieer blokattributen

Nu heb je een plaats nodig om gebruikersinstellingen op te slaan. Bijvoorbeeld het aantal postitems dat uit de database opgehaald moet worden, of een bepaald veld wel of niet getoond moet worden, enz. Om dat te doen definieer je een aantal attributes in het block.json bestand.

Je zou de gebruiker bijvoorbeeld de mogelijkheid kunnen geven om het aantal in het blok op te nemen berichten te bepalen, de optie om uitgelichte afbeeldingen, datum, exceprt te tonen, en/of de profielfoto van de auteur te verbergen/tonen.

Hier is de volledige lijst van attributen die we zullen gebruiken om ons voorbeeldblok te bouwen:

{
	...
	"attributes": {
		"numberOfItems": {
			"type": "number",
			"default": 3
		},
		"columns": {
			"type": "number",
			"default": 1
		},
		"displayDate": {
			"type": "boolean",
			"default": true
		},
		"displayExcerpt": {
			"type": "boolean",
			"default": true
		},
		"displayThumbnail": {
			"type": "boolean",
			"default": true
		},
		"displayAuthorInfo": {
			"type": "boolean",
			"default": true
		},
		"showAvatar": {
			"type": "boolean",
			"default": true
		}, 
		"avatarSize": {
			"type": "number",
			"default": 48
		},
		"showBio": {
			"type": "boolean",
			"default": true
		}
	}
}

Bouw het te tonen blok in de editor

De getEntityRecords selector zit in de @wordpress/data package. Om hem te gebruiken moet je de useSelect hook uit deze package in je edit.js bestand importeren:

import { useSelect } from '@wordpress/data';

Voeg vervolgens de volgende code toe aan de Edit() functie:

const posts = useSelect( ( select ) => {
	return select( 'core' ).getEntityRecords( 'postType', 'post', {
		'per_page': 3
	});
});

In de code hierboven hebben we het aantal berichten hardgecodeerd. Maar misschien wil je gebruikers de mogelijkheid geven een ander aantal berichten in te stellen. Je kunt daarvoor een attribuut gebruiken.

In je block.json zou je een numberOfItems attribuut gedefinieerd moeten hebben. Je kunt het gebruiken in je Edit functie zoals hieronder:

export default function Edit( { attributes } ) {

	const { numberOfItems } = attributes;

	const posts = useSelect( ( select ) => {
		return select( 'core' ).getEntityRecords( 'postType', 'post', {
			'per_page': numberOfItems
		});
	});

	console.log( posts );

	return (
		...
	);
}

Je zult de berichten nog niet op het scherm zien, maar voer een console.log uit en kijk wat er gebeurt in de console van je browser-inspector:

Het resultaat in de console van de browser.
Het resultaat in de console van de browser.

useSelect kan twee argumenten nemen: een inline callback en een array van dependencies. Beide geven een gememoiseerde versie van de callback terug die alleen verandert als een van de dependencies verandert.

Om berichten bij elke numberOfItems attribuutwijziging opnieuw op te halen, moet je dus de Edit functie veranderen zoals hieronder:

export default function Edit( { attributes } ) {

	const { numberOfItems } = attributes;

	const posts = useSelect(
		( select ) => {
			return select( 'core' ).getEntityRecords( 'postType', 'post', {
				'per_page': numberOfItems
			});
		}, 
		[ numberOfItems ]
	);

	console.log(posts);

	return (
		...
	);
}

Vervolgens moet je je lijst van berichten renderen. Om dat te doen kun je de ingebouwde JavaScript map methode gebruiken:

export default function Edit( { attributes } ) {

	const { numberOfItems } = attributes;

	const posts = useSelect(
		( select ) => {
			return select( 'core' ).getEntityRecords( 'postType', 'post', {
				'per_page': numberOfItems
			});
		},
		[ numberOfItems ]
	);

	console.log(posts);
	
	return (
		<div { ...useBlockProps() }>
			<ul>
				{ posts && posts.map( ( post ) => {
					return (
						<li key={ post.id }>
							<h5>
								<a href={ post.link }>
									{ 
										post.title.rendered ? 
										post.title.rendered :
										__( 'Default title', 'author-plugin' )
									}
								</a>
							</h5>
						</li>
					)
				})}
			</ul>
		</div>
	);
}

Eerst controleert deze of je minstens één bericht in de array hebt, dan voert deze de loop uit.

Let op dat, omdat we de map methode met een React component gebruiken, we ook een key attribuut gebruiken om het post ID aan het huidige lijst-item toe te wijzen.

post.link en post.title.rendered geven respectievelijk de URL en de titel van het bericht weer.

De afbeelding hieronder toont de volledige lijst van de post objectproperties.

Het Post object.
Het Post object.

De code hierboven is slechts een basisvoorbeeld van het gebruik van getEntityRecords. Nu is het tijd om onze kennis in de praktijk te brengen.

Stel dat je wilt voorkomen dat je blok HTML tags weergeeft die de gebruiker aan de berichttitel kan hebben toegevoegd. WordPress biedt daarvoor een RawHTML component.

Eerst importeer je de component uit het @wordpress/element pakket:

import { RawHTML } from '@wordpress/element';

Vervolgens wrap je de berichttitel binnen een RawHTML element:

<div { ...useBlockProps() }>
	<ul>
		{ posts && posts.map((post) => {
			return (
				<li key={ post.id }>
					<h5>
						<a href={ post.link }>
							{ post.title.rendered ? (
								<RawHTML>
									{ post.title.rendered }
								</RawHTML>
							) : (
								__( 'Default title', 'author-plugin' )
							)}
						</a>
					</h5>
				</li>
			)
		})}
	</ul>
</div>

En dat is het. Voeg nu een HTML tag toe aan je berichttitel en sla het bericht op. Test dan je code met en zonder RawHTML en kijk hoe de inhoud van je blok op het scherm verandert.

Voeg de datum toe

WordPress biedt een aantal JavaScript functies om datums te beheren en op te maken. Om die functies te gebruiken moet je ze eerst uit het @wordpress/date pakket importeren in je edit.js bestand:

import { dateI18n, format, __experimentalGetSettings } from '@wordpress/date';
  • dateI18n: Formatteer een datum, door hem te vertalen naar de gelokaliseerde instellingen van de site.
  • format: Formatteer een datum.
  • __experimentalGetSettings: Geef de datum weer in het formaat dat ingesteld is in de algemene instellingen van WordPress.

Die functies zijn niet gedocumenteerd, maar je vindt nuttige voorbeelden in de broncode van verschillende blokken. Zie bijvoorbeeld de bestanden latest-posts en post-date edit.js.

Voeg nu het displayDate attribuut toe:

const { numberOfItems, displayDate } = attributes;

Voeg nu de volgende code toe binnen het <li> element:

{ 
	displayDate && (
		<time
			className='wp-block-author-box-author-plugin__post-date'
			dateTime={ format( 'c', post.date_gmt ) }
		>
			{ dateI18n(
				__experimentalGetSettings().formats.date, 
				post.date_gmt
			)}
		</time>
	) 
}

Wat gebeurt hier?

  • Als displayDate is true, geef dan de datum weer met een time element.
  • Het dateTime attribuut geeft de tijd en/of datum van het element in een van de toegestane formaten.
  • dateI18n haalt de datum op in een gelokaliseerd formaat. Deze functie werkt op een soortgelijke manier als de PHPPHP date_i18n WordPress functie.

Voeg het excerpt toe

Nu zou het eenvoudig moeten zijn om het berichtexcerpt toe te voegen. Kijk eerst naar de excerpt propertyin de inspector van de browser. Je ziet dat de eigenlijke inhoud is opgeslagen in excerpt.rendered.

Inspecteren van het berichtexcerpt in Chrome DevTools.
Inspecteren van het berichtexcerpt in Chrome DevTools.

Voeg vervolgens het displayExcerpt attribuut toe aan het attributes object:

const { numberOfItems, displayDate, displayExcerpt } = attributes;

Voeg dan de volgende code toe vóór de </li> sluit-tag in de functie Edit:

{
	displayExcerpt &&
	post.excerpt.rendered && (
		<p>
			<RawHTML>
				{ post.excerpt.rendered }
			</RawHTML>
		</p>
	)
}

Als je niet vertrouwd bent met JavaScript, gebruikten we hier en hierboven de Short Circuit Evaluation, waarbij, als alle voorwaarden waar zijn, de waarde van de laatste operand wordt teruggegeven (lees meer in Inline If with Logical && Operator en Logical AND (&&)).

Tenslotte kun je je code opnieuw testen. Verander de waarde van het attribuut in het block.json bestand en kijk wat er in de editor gebeurt.

Voeg de uitgelichte afbeelding toe

Nu moet je de code toevoegen die de uitgelichte afbeeldingen rendert. Begin met het toevoegen van het displayThumbnail attribuut aan attributes:

const { 
	numberOfItems, 
	displayDate, 
	displayExcerpt, 
	displayThumbnail 
} = attributes;

Nu moet je uitzoeken waar de uitgelichte afbeelding wordt opgeslagen. Zoals we hierboven al zeiden, moet je om de uitgelichte afbeelding te krijgen een nieuw _embed argument aan je query toevoegen. In je code verander je de query argumenten als volgt:

const posts = useSelect(
	( select ) => {
		return select( 'core' ).getEntityRecords( 'postType', 'post', {
			'per_page': numberOfItems,
			'_embed': true
		});
	},
	[ numberOfItems ]
);

Hier voegden we eenvoudig '_embed': true toe aan de array van argumenten. Dit levert een post object op dat de property _embedded bevat, die de afbeeldingsgegevens geeft die je nodig hebt om de uitgelichte beelden te tonen.

Nu moet je weten waar je de afbeeldingsdetails kunt vinden.

Uitgelichte beelddetails in getEntityRecords antwoord.
Uitgelichte beelddetails in getEntityRecords antwoord.

Je hoeft alleen maar de code toe te voegen die het beeld op het scherm rendert:

{
	displayThumbnail && 
	post._embedded && 
	post._embedded['wp:featuredmedia'] &&
	post._embedded['wp:featuredmedia'][0] &&
	<img 
	className='wp-block-author-box-author-plugin__post-thumbnail'
		src={ post._embedded['wp:featuredmedia'][0].media_details.sizes.medium.source_url }
		alt={ post._embedded['wp:featuredmedia'][0].alt_text }
	/>
}

Sla het bestand op, schakel over naar de blok-editor, en kijk of de afbeelding correct wordt weergegeven als het displayThumbnail attribuut ingesteld is op true.

Een lijst van berichten met uitgelichte afbeelding, datum en uittreksel.
Een lijst van berichten met uitgelichte afbeelding, datum en uittreksel.

Voeg zijbalkcontrols toe

Tot nu toe hebben we de standaardwaarden van het attribuut gebruikt die in de block.json zijn ingesteld. Maar uit ons vorige artikel weten we dat we event handlers kunnen definiëren om gebruikers de mogelijkheid te geven aangepaste waarden aan elk attribuut toe te kennen.

Om dat te doen voeg je een stel controls toe aan de zijbalk met blokinstellingen. Importeer in edit.js de volgende componenten uit de overeenkomstige packages:

import { 
	useBlockProps,
	InspectorControls
} from '@wordpress/block-editor';

import {
	PanelBody,
	PanelRow,
	QueryControls,
	ToggleControl,
	RangeControl
} from '@wordpress/components';
  • InspectorControls: Bevat zijbalkinstellingen die het hele blok beïnvloeden (zie op GitHub).
  • PanelBody: Voegt een inklapbare container toe aan de instellingenzijbalk (zie op GitHub)
  • PanelRow: Produceert een generieke container voor zijbalkcontrols (zie op GitHub)
  • QueryControls: Biedt controls voor instellingen om een query te bouwen (zie op GitHub)
  • ToggleControl: Biedt een toggleknop waarmee gebruikers een bepaalde optie kunnen in-/uitschakelen (zie op GitHub)
  • RangeControl: Wordt gebruikt om selecties te maken uit een reeks oplopende waarden (zie op GitHub)

Vervolgens moet je de functie Edit bijwerken om de nu beschikbare controls te gebruiken. Eerst wijzig je de functie Edit als volgt:

export default function Edit( { attributes, setAttributes } ) {

	const { 
		numberOfItems, 
		columns, 
		displayExcerpt, 
		displayDate, 
		displayThumbnail
	} = attributes;

	const posts = useSelect(
		( select ) => {
			return select( 'core' ).getEntityRecords( 'postType', 'post', {
				'per_page': numberOfItems,
				'_embed': true
			});
		},
		[ numberOfItems ]
	);
	...
}

Let op de setAttributes eigenschap die aan de functie Edit wordt doorgegeven.

Nu kun je de overeenkomstige elementen aan je JSX code toevoegen:

return (
	<>
		<InspectorControls>
			<PanelBody title={ __( 'Content Settings', 'author-plugin' ) }>
				<PanelRow>
					<QueryControls 
						numberOfItems={ numberOfItems }
						onNumberOfItemsChange={ ( value ) =>
							setAttributes( { numberOfItems: value } )
						}
						minItems={ 1 }
						maxItems={ 10 }
					/>
				</PanelRow>
				<PanelRow>
					<RangeControl
						label={ __( 'Number of Columns', 'author-plugin' ) }
						value={ columns }
						onChange={ ( value ) =>
							setAttributes( { columns: value } )
						}
						min={ 1 }
						max={ 4 }
						required
					/>
				</PanelRow>
				<PanelRow>
					<ToggleControl
						label={ __( 'Show Featured Image', 'author-plugin' ) }
						checked={ displayThumbnail }
						onChange={ () =>
							setAttributes( { displayThumbnail: ! displayThumbnail } )
						}
					/>
				</PanelRow>
				<PanelRow>
					<ToggleControl
						label={ __( 'Show Date', 'author-plugin' ) }
						checked={ displayDate }
						onChange={ () =>
							setAttributes( { displayDate: ! displayDate } )
						}
					/>
				</PanelRow>
				<PanelRow>
					<ToggleControl
						label={ __( 'Display Excerpt', 'author-plugin' ) }
						checked={ displayExcerpt }
						onChange={ () =>
							setAttributes( { displayExcerpt: ! displayExcerpt } )
						}
					/>
				</PanelRow>
			</PanelBody>
		</InspectorControls>
		<div { ...useBlockProps() }>
			...
		</div>
	</>
);

Wauw, toch wel een hoop code. Schrik niet, het is vrij gemakkelijk te begrijpen.

De element attributen die hier het meest je aandacht verdienen zijn onNumberOfItemsChange in QueryControls en onChange in RangeControl en ToggleControl. Die attributen stellen de event handlers in die nodig zijn om de gebruiker in staat te stellen het uiterlijk en/of het gedrag van een blok aan te passen.

Je zult ook merken dat we <> en </> tags gebruikten, wat de korte syntaxis is voor het declareren van React fragmenten.

Sla nu je bestand op, ga naar de editor, en vernieuw de pagina:

Blokinstellingen.
Blokinstellingen.

Staat alles er in? Laten we dan verder gaan en de gegevens van de auteur van de post toevoegen.

Zoek de auteur van het bericht

Zoals we hierboven al zeiden, toont ons blok een lijst van artikelen die door dezelfde auteur als de huidige post zijn geschreven.

Om het ID van de post auteur te krijgen, importeer je de getCurrentPostAttribute selector uit de core/editor data store:

wp.data.select( 'core/editor' ).getCurrentPostAttribute( 'author' )

getCurrentPostAttribute geeft een attribuutwaarde voor het bewaarde bericht terug.

Als je eenmaal het auteur ID hebt, kun je de query veranderen zoals hieronder:

const posts = useSelect(
	( select ) => {

		const _authorId = select( 'core/editor' ).getCurrentPostAttribute( 'author' );
	
		return select( 'core' ).getEntityRecords( 'postType', 'post', {
			'author': _authorId,
			'per_page': numberOfItems,
			'_embed': true
		});
	},
	[ numberOfItems ]
);

Met deze code krijg je een lijst van n artikelen van dezelfde auteur als de huidige post.

Nu we hebben over het auteur ID hebben, kunnen we het ook gebruiken om aanvullende gegevens uit de database te halen.

Toon details over de auteur

Omdat we geen documentatie beschikbaar hebben, gebruikten we de code uit het coreblok Post Author  als referentie.

Om auteursdetails te tonen, moet je eerst een nieuwe dependencies importeren:

import { forEach } from 'lodash';

Werk dan, in de functie Edit, het object attributes als volgt bij:

const { 
	numberOfItems, 
	columns, 
	displayExcerpt, 
	displayDate, 
	displayThumbnail, 
	displayAuthorInfo, 
	showAvatar, 
	avatarSize, 
	showBio 
} = attributes;

Als je dat gedaan hebt, bewerk je de code die je in de vorige paragraaf zag om auteursgegevens op te halen:

const { authorDetails, posts } = useSelect(
	( select ) => {

		const _authorId = select( 'core/editor' ).getCurrentPostAttribute( 'author' );

		const authorDetails = _authorId ? select( 'core' ).getUser( _authorId ) : null;
	
		const posts = select( 'core' ).getEntityRecords( 'postType', 'post', {
			'author': _authorId,
			'per_page': numberOfItems,
			'_embed': true
		});

		return { 
			authorDetails: authorDetails,
			posts: posts
		};
	},
	[ numberOfItems ]
);

Merk op dat we de getUser selector gebruikten om de auteursdetails op te halen.

Vervolgens wil je misschien de avatar van de auteur opvragen. De onderstaande code bouwt een array van items die avatar URL’s en afmetingen opslaan:

const avatarSizes = [];
if ( authorDetails ) {
	forEach( authorDetails.avatar_urls, ( url, size ) => {
		avatarSizes.push( {
			value: size,
			label: `${ size } x ${ size }`,
		} );
	} );
}

Dan voeg je de zijbalkpanelen en controls toe om gebruikers in staat te stellen het auteursgedeelte in het blok aan te passen:

return (
	<>
		<InspectorControls>
			<PanelBody title={ __( 'Author Info', 'author-plugin' ) }>
				<PanelRow>
					<ToggleControl
						label={ __( 'Display Author Info', 'author-plugin' ) }
						checked={ displayAuthorInfo }
						onChange={ () =>
							setAttributes( { displayAuthorInfo: ! displayAuthorInfo } )
						}
					/>
				</PanelRow>
				{ displayAuthorInfo && (
					<>
						<PanelRow>
							<ToggleControl
								label={ __( 'Show avatar' ) }
								checked={ showAvatar }
								onChange={ () =>
									setAttributes( { showAvatar: ! showAvatar } )
								}
							/>
							{ showAvatar && (
								<SelectControl
									label={ __( 'Avatar size' ) }
									value={ avatarSize }
									options={ avatarSizes }
									onChange={ ( size ) => {
										setAttributes( {
											avatarSize: Number( size ),
										} );
									} }
								/>
							) }
						</PanelRow>
						<PanelRow>
							<ToggleControl
								label={ __( 'Show Bio', 'author-plugin' ) }
								checked={ showBio }
								onChange={ () =>
									setAttributes( { showBio: ! showBio } )
								}
							/>
						</PanelRow>
					</>
				) }
			</PanelBody>
			...
		</InspectorControls>
		...
	</>
);

De afbeelding hieronder toont de bijgewerkte instellingenzijbalk:

Het instellingenpaneel Author Info.
Het instellingenpaneel Author Info.

Tenslotte kun je het auteursgedeelte aan je blok toevoegen:

return (
	<>
		<InspectorControls>
		...
		</InspectorControls>

		<div { ...useBlockProps() }>
			{ displayAuthorInfo  && authorDetails && (
				<div className="wp-block-author-box-author-plugin__author">
					{ showAvatar && (
						<div className="wp-block-author-box-author-plugin__avatar">
							<img
								width={ avatarSize }
								src={
									authorDetails.avatar_urls[
										avatarSize
									]
								}
								alt={ authorDetails.name }
							/>
						</div>
					) }
					<div className='wp-block-author-box-author-plugin__author-content'>
						<p className='wp-block-author-box-author-plugin__name'>
							{ authorDetails.name }
						</p>
						{ showBio &&
							// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
							authorDetails?.description &&
							authorDetails.description.length > 0 && (
							<p className='wp-block-author-box-author-plugin__description'>{ authorDetails.description }</p>
						) }
					</div>
				</div>
			)}
			<ul>
			...
			</ul>
		</div>
	</>
);

De volgende afbeelding toont hoe het op het scherm rendert.

Auteursgegevens sectie en Info instellingen.
Auteursgegevens sectie en Info instellingen.

Sla nu je edit.js bestand op en voer je tests uit. Je blok zou verschillende elementen moeten bevatten, afhankelijk van de blokinstellingen.

Auteursdetails tonen niet de bio van de auteur.
Auteursdetails tonen niet de bio van de auteur.

Een laatste ding ontbreekt nog: het aantal kolommen om artikelen weer te geven.

Verander het aantal kolommen

Om de gebruiker de mogelijkheid te geven artikelvoorbeelden in kolommen te tonen, definieerden we het columns attribuut in het block.json bestand. We namen ook een columns attribuut op in het script en maakten een instellingen-bedieningselement waarmee gebruikers het aantal kolommen kunnen veranderen, hoewel deze verandering nu nog geen effect heeft.

In de JSX code hierboven moet je gemerkt hebben dat we CSS klassen aan verschillende elementen toevoegden:

Klassen toegekend aan elementen in de sectie Author:

  • wp-block-author-box-author-plugin__author
  • wp-block-author-box-author-plugin__avatar
  • wp-block-author-box-author-plugin__author-content
  • wp-block-author-box-author-plugin__name
  • wp-block-author-box-author-plugin__description

Klassen toegekend aan elementen in de inhoudssectie:

  • wp-block-author-box-author-plugin__post-items
  • wp-block-author-box-author-plugin__post-thumbnail
  • wp-block-author-box-author-plugin__post-title
  • wp-block-author-box-author-plugin__post-date
  • wp-block-author-box-author-plugin__post-excerpt

Eén klasse ontbreekt nog. De naam van deze klasse zal dynamisch gegenereerd worden om het door de gebruiker ingestelde aantal kolommen weer te geven.

Ga terug naar het Edit.js bestand en wijzig het ul element als volgt:

<ul className={ `wp-block-author-box-author-plugin__post-items columns-${ columns }` }>
	...
</ul>

We voegden een nieuwe columns-${ columns } klasse toe volgens de syntaxis van Template literals om een expressie binnen een string in te voegen. Op deze manier hangt het attribuut dat aan het ul element hangt af van gebruikersinstellingen (bv. columns-1, columns-2, enz.).

Open nu het style.scss bestand en vervang de bestaande code door het volgende:

.wp-block-author-box-author-plugin {
	background-color: #21759b;
	color: #fff;
	padding: .6em;
	ul.wp-block-author-box-author-plugin__post-items {
		padding: 0;
		list-style-type: none;
		display: grid;
		gap: .5em;
		@for $i from 2 through 4 {
			&.columns-#{ $i } {
				grid-template-columns: repeat(#{ $i }, 1fr);
			}
		}
		li {
			list-style: none;
			img.wp-block-author-box-author-plugin__post-thumbnail {
				height: auto;
				max-width: 100%;
			}
		}
		
	}
}
.wp-block-author-box-author-plugin__author {
	display: flex;
    flex-wrap: wrap;
}

.wp-block-author-box-author-plugin__avatar {
	margin-right: 1em;
}

.wp-block-author-box-author-plugin__author-content {
	flex-basis: 0;
    flex-grow: 1;
}

We gaan niet dieper in op die code, want die valt buiten het bestek van dit artikel. Maar als je er meer over wil lezen, kun je de volgende bronnen raadplegen:

Het blok Author in de editor.
Het blok Author in de editor.

En dat was het voor de rendering van het blok in de editor.

Het blok bouwen om op de pagina te renderen

Nu de code die het blok in de editor rendert klaar is, kunnen we verder gaan en het blok bouwen voor rendering aan de frontend.

Zoals we eerder zeiden, is bij dynamische blokken het pluginbestand verantwoordelijk voor het genereren van de HTML die aan de voorkant moet worden weergegeven.

Open dus het hoofdbestand van je plugin(author-plugin.php in ons voorbeeld).

Het eerste wat je moet doen is de blokattributen beschikbaar maken voor de WordPress PHP functie. Verander in je PHP bestand de functiedefinitie als volgt:

function author_box_author_plugin_render_author_content( $attr ) {
	...
}

Nu kun je de WordPress functies gebruiken om gegevens op te halen en te manipuleren. Je kunt bijvoorbeeld get_posts gebruiken om de nieuwste blogberichten op te halen (lees meer in ons diepgaande artikel over de get_posts functie):

function author_box_author_plugin_render_author_content( $attr ) {
	$args = array(
		'numberposts'	=> $attr['numberOfItems'],
	);
	$my_posts = get_posts( $args );
	
	if( ! empty( $my_posts ) ){
		$output = '<ul>';
		foreach ( $my_posts as $p ){
			$output .= '<li><a href="' . esc_url( get_permalink( $p->ID ) ) . '">' 
			. $p->post_title . '</a></li>';
		}
		$output .= '</ul>';
	}
	return $output ?? '<strong>Sorry. No posts matching your criteria!</strong>';
}

De functie hierboven haalt de nieuwste numberOfItems blogberichten op uit je WordPress database (standaard staat post_type op post) en geeft een array van $post objecten terug. Dan itereert het over de array om de lijstitems te bouwen.

Als je de HTML uitvoer inspecteert, zie je dat het een eenvoudige lijst van berichten is, zoals die in de volgende afbeelding:

Een eenvoudige lijst van berichten.
Een eenvoudige lijst van berichten.

In ons vorige artikel meldden we dat je de useBlockProps React hook gebruikt om het wrapper element van het blok te markeren in je JSX code. Je zult hetzelfde moeten doen in je PHP functie.

WordPress biedt daarvoor de functieget_block_wrapper_attributes .

Verander dus je PHP code als volgt:

function author_box_author_plugin_render_author_content( $attr ) {
	$args = array(
		'numberposts'	=> $attr['numberOfItems']
	);
	$my_posts = get_posts( $args );
	
	if( ! empty( $my_posts ) ){
		$output = '<div ' . get_block_wrapper_attributes() . '>';
		$output .= '<ul>';
		foreach ( $my_posts as $p ){
			
			$title = $p->post_title ? $p->post_title : 'Default title';
			$url = esc_url( get_permalink( $p->ID ) );

			$output .= '<li>';
			$output .= '<a href="' . $url . '">' . $title . '</a>';
			$output .= '</li>';
		}
		$output .= '</ul>';
		$output .= '</div>';
	}
	return $output ?? '<strong>Sorry. No posts matching your criteria!</strong>';
}

Nu is aan het container element een wp-block-author-box-author-plugin klasse toegekend en heeft het blok een andere achtergrondkleur.

Vervolgens krijgt de get_posts functie WP_Posts gegevens en de foreach cyclus bouwt de lijstitems (zie ook Zo toon je get_posts getourneerde data).

Een lijst van berichten waaraan een CSS klasse is toegekend.
Een lijst van berichten waaraan een CSS klasse is toegekend.

Voeg uitgelichte afbeelding, datum en excerpt toe

Vervolgens moet je thumbnails, datums en excerpts van je bericht toevoegen. Verander in hetzelfde bestand je PHP code als volgt:

function author_box_author_plugin_render_author_content( $attr ) {
	$args = array(
		'numberposts'	=> $attr['numberOfItems']
	);
	$my_posts = get_posts( $args );
	
	if( ! empty( $my_posts ) ){
		$output = '<div ' . get_block_wrapper_attributes() . '>';
		$output .= '<ul class="wp-block-author-box-author-plugin__post-items columns-">';

		foreach ( $my_posts as $p ){
			
			$title = $p->post_title ? $p->post_title : 'Default title';
			$url = esc_url( get_permalink( $p->ID ) );
			$thumbnail = has_post_thumbnail( $p->ID ) ? get_the_post_thumbnail( $p->ID, 'medium' ) : '';

			$output .= '<li>';
			if( ! empty( $thumbnail ) && $attr['displayThumbnail'] ){
				$output .= $thumbnail;
			}
			$output .= '<h5><a href="' . $url . '">' . $title . '</a></h5>';
			if( $attr['displayDate'] ){
				$output .= '<time datetime="' . esc_attr( get_the_date( 'c', $p ) ) . '">' . esc_html( get_the_date( '', $p ) ) . '</time>';
			}
			if( get_the_excerpt( $p ) && $attr['displayExcerpt'] ){
				$output .= '<p>' . get_the_excerpt( $p ) . '</p>';
			}
			$output .= '</li>';
		}
		$output .= '</ul>';
		$output .= '</div>';
	}
	return $output ?? '<strong>Sorry. No posts matching your criteria!</strong>';
}

De foreach loop itereert over de $my_posts array. Bij elke iteratie controleren verschillende condities de attribuutwaarden en bouwen de uitvoer dienovereenkomstig op.

Kijk nu eens naar de uitvoer op het scherm:

Een lijst van berichten met uitgelichte beelden, data, en uittreksels.
Een lijst van berichten met uitgelichte beelden, data, en uittreksels.

Nu kun je je tests uitvoeren. Verander de instellingen voor datum, uittreksel en thumbnail en kijk hoe de blokinhoud verandert aan de frontend.

Geef berichten weer in kolommen

In onze JavaScript code gebruikten we een columns-${ columns } klasse om berichtpreviews in kolommen weer te geven. Nu moeten we hetzelfde doen in PHP.

Om dat te doen hoef je alleen maar deze twee regels code toe te voegen:

$num_cols = $attr['columns'] > 1 ? strval( $attr['columns'] ) : '1';

$output .= '<ul class="wp-block-author-box-author-plugin__post-items columns-' . $num_cols . '">';

Dit zal een columns-n klasse toevoegen aan het ul element dat de berichtpreviews bevat. Nu moet het aantal kolommen dat op de pagina wordt getoond overeenkomen met het aantal kolommen dat in de blokinstellingen is ingesteld.

Bouw de auteursbox

Als laatste moet je de box bouwen met de gegevens van de auteur, waaronder avatar, naam, en beschrijving.

Binnen de callback functie moet je een reeks voorwaarden toevoegen om de huidige waarde van elk attribuut te controleren:

if( $attr['displayAuthorInfo'] ){
	$output .= '<div class="wp-block-author-box-author-plugin__author">';
	
	if( $attr['showAvatar'] ){
		$output .= '<div class="wp-block-author-box-author-plugin__avatar">' 
			. get_avatar( get_the_author_meta( 'ID' ), $attr['avatarSize'] ) 
			. '</div>';
	}

	$output .= '<div class="wp-block-author-box-author-plugin__author-content">';
	
	$output .= '<div class="wp-block-author-box-author-plugin__name">' 
		. get_the_author_meta( 'display_name' ) 
		. '</div>';

	if( $attr['showBio'] ){
		$output .= '<div class="wp-block-author-box-author-plugin__description">' 
			. get_the_author_meta( 'description' ) 
			. '</div>';
	}

	$output .= '</div>';
	$output .= '</div>';
}

De code is vrij rechttoe rechtaan. Het controleert de huidige waarde van elk attribuut, en als het true is, dan genereert het de nodige HTML.

Sla nu je PHP bestand op en vergelijk het blok in de editor vs. hetzelfde blok aan de frontend.

Ons aangepaste blok in de blok editor.
Ons aangepaste blok in de blok editor.

Je vindt de volledige code van het voorbeeldblok in deze openbare Gist.

Aanbevolen bronnen voor dynamische blokontwikkeling

Als je tijdens het lezen van dit artikel maar geen genoeg kon krijgen van de informatie en de mogelijkheden voor professionele ontwikkeling begon te herkennen die komen met het leren maken van Gutenberg blokken, dan is ons advies om door te gaan met het verkennen en verwerven van nieuwe vaardigheden in de technologieën achter blokontwikkeling.

Hoewel betrouwbare officiële documentatie nog ontbreekt, zijn er niettemin uitstekende bronnen beschikbaar, zowel gratis als betaald, die we tijdens het schrijven van dit artikel raadpleegden. Van de vele beschikbare bronnen bevelen we de volgende aan:

Officiële bronnen

Aanbevolen handleidingen van WordPress Core medewerkers

JavaScript, React, en Redux Hulpmiddelen

Verwante bronnen van Kinsta

Samenvatting

We zijn aan het eind gekomen van deze (tweede) lange reis door Gutenberg blokontwikkeling.

In dit artikel hebben we enkele geavanceerde onderwerpen behandeld, zoals Application State en Redux stores. Maar hopelijk zou je nu een beter begrip moeten hebben van blokontwikkeling in het algemeen.

Ja, Node.js, Webpack, Babel, React, en Redux vaardigheden zijn essentieel als het gaat om het bouwen van geavanceerde Gutenberg blokken, maar je hoeft geen React ninja te zijn om aan de slag te gaan. Leren hoe je Gutenberg blokken kunt ontwikkelen hoeft niet ingewikkeld te zijn. Doe het met de juiste motivatie en door het juiste leertraject te volgen.

En we hopen dat dit artikel – en het vorige – je de juiste kaart geven om jouw eigen pad te vinden en meteen met Gutenberg ontwikkeling aan de slag te gaan.

Nu is het jouw beurt! Heb je al eens dynamische blokken gemaakt? Heb je voorbeelden om met ons te delen? En wat waren de grootste hindernissen? Voel je vrij om hieronder een reactie te laten vallen.

Carlo Daniele Kinsta

Carlo is a passionate lover of webdesign and front-end development. He has been playing with WordPress for more than 20 years, also in collaboration with Italian and European universities and educational institutions. He has written hundreds of articles and guides about WordPress, published both on Italian and international websites, as well as on printed magazines. You can find him on LinkedIn.