hey
wp

Ressourcen für WordPress-Entwickler*innen

  • Ein einfacher Gutenberg-Block, selbst programmiert (Teil 2/2)

    Wenn es an deinen ersten eigenen Gutenberg-Block geht gilt eines vorneweg zu beachten: Wir arbeiten hier mit zwei Blocks – einen für den Stadtplan und einen weiteren für die Wegpunkte.

    Das Elternelement

    Lege los im Plugins-Ordner deiner lokalen WP-Installation:

    npx @wordpress/create-block@latest berlin-map-parent —variant=dynamic
    cd berlin-map-parent
    npm start

    Widme dich zunächst der block.json:

    {
     "$schema": "https://schemas.wp.org/trunk/block.json",
     "apiVersion": 3,
     "name": "create-block/berlin-map-parent",
     "version": "0.1.0",
     "title": "Berlin Map Parent",
     "category": "widgets",
     "icon": "multisite",
     "description": "Berlin Map Parent",
     "example": {},
     "supports": {
        "html": false
    },
     "allowedBlocks": ["create-block/berlin-map-child"],
     "textdomain": "berlin-map-parent",
     "editorScript": "file:./index.js",
     "editorStyle": "file:./index.css",
     "style": "file:./style-index.css",
     "viewScript": "file:./view.js"
    }

    Oben markiert habe ich für dich allowedBlocks – du siehst, hier wird das erlaubte Unterelement definiert.

    Nun geht es weiter mit der edit.js, um die Darstellung im WP-Block-Editor im Backend einzurichten:

    .import { __ } from '@wordpress/i18n';
    import { InnerBlocks, useBlockProps } from "@wordpress/block-editor";
    import "./editor.scss";
    export default function Edit() {
        const blockProps = useBlockProps();
    
        return (
    
        <div {...blockProps}>
    
        <div id="karte">
    
        <img src="/wp-content/plugins/berlin-map-parent/src/berlin-map-parent/berlin-map.svg" 
        height="411"
        width="500" alt="Berlin-Karte" />
    
        <InnerBlocks />
    
        </div>
    </div>
    );
    }

    Ist dir InnerBlocks ins Auge gefallen ? An jener Stelle sollen später die Wegmarken im HTML-Markup erscheinen.

    Die index.js ist für dich leicht verständlich, wenn du dir meinen Teil 1 angesehen hast 🙂 So sieht sie aus:

    import { registerBlockType } from '@wordpress/blocks';
    import './style.scss';
    import Edit from './edit';
    import save from './save';
    import metadata from './block.json';
        registerBlockType( metadata.name, {
            edit: Edit,
            save,
        } 
    ); 

    Fahren wir fort mit der save.js und ihrem zur edit.js nahezu identischen Code:

    import { InnerBlocks, useBlockProps } from "@wordpress/block-editor";
    const Save = () => {
        const blockProps = useBlockProps.save();
        return (
            <div {...blockProps}>
                <div id="karte">
                <img src="/wp-content/plugins/berlin-map-parent/src/berlin-map-parent/berlin-map.svg"
                height="411" width="500" alt="Berlin-Karte" />
                <InnerBlocks.Content />
                </div>
            </div>
        );
    };
    export default Save;

    In der style.scss machen wir die Karte und alles innerhalb relativ

    #karte, #karte * {
        position: relative;
    }

    Nun können wir das Elternelement in Aktion sehen:

    Berlin-Karte im WP-Editor

    Das Kindelement: Die Wegpunkte

    Nun geht es erneut los im Plugins-Ordner deiner WP-Installation:

    npx @wordpress/create-block@latest berlin-map-child —variant=dynamic
    cd berlin-map-child
    npm start

    Nun die block.json:

    {
     "$schema": "https://schemas.wp.org/trunk/block.json",
     "apiVersion": 3,
     "name": "create-block/berlin-map-child",
     "version": "0.1.0",
     "title": "Berlin Map Child",
     "category": "widgets",
     "icon": "location",
     "description": "Berlin Map Child",
     "example": {},
     "supports": {
        "html": false
     },
     "parent": ["create-block/berlin-map-parent"],
     "textdomain": "berlin-map-child",
     "editorScript": "file:./index.js",
     "editorStyle": "file:./index.css",
     "style": "file:./style-index.css",
     "viewScript": "file:./view.js",
     "attributes": {
         "link": {
             "type": "string",
             "default": "https://berlin.de"
         },
         "buttonText": {
             "type": "string",
             "default": „Mitte"
         },
         "top": {
             "type": "number",
             "default": 300
         },
         "left": {
             "type": "number",
             "default": 230
         }
     },
    }

    Nun wird im Gegenzug definiert, dass dieses Element nur die Kartengrafik als Elternteil besitzen darf. Die Attribute geben Aufschluss über die folgenden Konfigurationen im rechten Seitenpanel: Verlinkung, Beschriftung und die Koordinaten „oben“ und „links“.

    Nun die edit.js:

    import { __ } from "@wordpress/i18n";
    import {
        RichText, useBlockProps, InspectorControls,
    } from "@wordpress/block-editor";
    import { PanelBody, TextControl, RangeControl } from "@wordpress/components";
    import "./editor.scss";
    const Edit = (props) => {
        const {
            attributes: { link, buttonText, top, left },
            setAttributes,
        } = props;
        const blockProps = useBlockProps();
        const onChangeLink = (value) => {
            setAttributes({ link: value });
        };
        const onChangeButtonText = (value) => {
            setAttributes({ buttonText: value });
        };
        const onChangeTop = (value) => {
            setAttributes({ top: value });
        };
        const onChangeLeft = (value) => {
            setAttributes({ left: value });
        };
        return (
            <>
            <InspectorControls>
            <PanelBody title= { __("Einstellungen", "berlin-map-child") } >
            <TextControl
    label={ __("Button Text", "berlin-map-child") }
        value = { buttonText }
        onChange = { onChangeButtonText }
        placeholder = { __("Location name", "berlin-map-child") }
            />
            <TextControl
    label={ __("Link", "berlin-map-child") }
        value = { link }
        onChange = { onChangeLink }
        placeholder = { __("https://berlin.de", "berlin-map-child") }
            />
            <RangeControl
    label={ __("Top Position (px)", "berlin-map-child") }
        value = { top }
        onChange = { onChangeTop }
        min = { 0}
        max = { 1000}
        step = { 1}
            />
            <RangeControl
    label={
            __("Left Position (px)", "berlin-map-child")
        }
        value = { left }
        onChange = { onChangeLeft }
        min = { 0}
        max = { 1000}
        step = { 1}
            />
            </PanelBody>
            </InspectorControls>
    
            < div { ...blockProps } >
                <a style={ { left: `${left}px`, top: `${top}px`, position: "absolute" } }
        href = { link } >
            <RichText
    placeholder={
            __(
                "Mitte",
                "berlin-map-child",
            )
        }
        value = { buttonText }
        onChange = { onChangeButtonText }
            />
            </a>
            </div>
            </>
    );
    };
    export default Edit;

    RangeControl sind also Schiebereegler, um die Position von oben und links im rechten Panel von WordPress einstellen zu könne.

    Machen wir weiter mit der editor.scss. Wie der Name dir sagt, wird sie später nicht öffentlich ausgespielt, aber sorgt bei dir im WP-Editor für alles nötige:

    .wp-block-create-block-berlin-map-child {
        border: 1px dotted #f00;
    }
    .wp-block-create-block-berlin-map-parent .block-editor-inner-blocks,
    .wp-block-create-block-berlin-map-parent .block-editor-block-list__layout {
        display: contents;
    }
    #karte a {
        position: absolute;
        color: red;
        display: flex;
        pointer-events: none;
    }
    #karte a:before {
        content: " ";
        display: inline-block;
        vertical-align: middle;
        margin-right: 4px;
        width: 15px;
        height: 15px;
        border: 3px solid white;
        border-radius: 15px;
        margin-bottom: 3px;
    }
    #karte .linksbuendig a:after {
        content: " ";
        display: inline-block;
        vertical-align: middle;
        margin-left: 4px;
        width: 15px;
        height: 15px;
        border: 3px solid white;
        border-radius: 15px;
        margin-bottom: 3px;
    }
    #karte .linksbuendig a:before {
        display: none;
    }

    Ein weiteres Herzstück ist die index.js – die ist dir ja jetzt nicht mer neu:

    import { registerBlockType } from '@wordpress/blocks';
    import './style.scss';
    import Edit from './edit';
    import save from './save';
    import metadata from './block.json';
    registerBlockType( metadata.name, {
        edit: Edit,
        save,
    } );

    Machen wir weiter mit der save.js:

    import { RichText, useBlockProps } from "@wordpress/block-editor";
    const Save = (props) => {
        const { attributes: { link, buttonText, top, left } } = props;
        const blockProps = useBlockProps.save();
        return (
            <div { ...blockProps } >
            <a
    style= {{ left: `${left}px`, top: `${top}px`, position: "absolute" }
    }
    href = { link }
        >
        <RichText.Content value={ buttonText } />
            </a>
            </div>
    );
    };
    export default Save;

    Bemerkenswert, wie gering der Code gegenüber der edit.js ausfällt und ein guter Moment nochmal den entscheidenden Unterschied zwischen edit.js und save.js hervorzuheben:

    Nun müssen ja Websitebesucher keine Wegpunkte einsetzen, und auch nicht deren Links und Positionen bestimmen. In deren Browser müssen alleine jene Werte ankommen, die in den Werkzeugen der edit.js festgelegt wurden und von uns dann eingesetzt wurden.

    Apropos Frontend – machen wir nun weiter mit der style.scss:

    .wp-block-create-block-berlin-map-child {
        display: contents;
    }
    #karte a {
        position: absolute;
        color: red;
        display: flex;
        pointer-events: none;
    }
    #karte a:before {
        content: " ";
        display: inline-block;
        vertical-align: middle;
        margin-right: 4px;
        width: 15px;
        height: 15px;
        border: 3px solid white;
        border-radius: 15px;
        margin-bottom: 3px;
    }
    #karte .linksbuendig a:after {
        content: " ";
        display: inline-block;
        vertical-align: middle;
        margin-left: 4px;
        width: 15px;
        height: 15px;
        border: 3px solid white;
        border-radius: 15px;
        margin-bottom: 3px;
    }
    #karte .linksbuendig a:before {
        display: none;
    }

    Und wie sehen die beiden Blocks nun aus ?

    Berlin-Karte mit Wegpunkten

    Hurra! Wir haben nun eine Berlinkarte, auf der wir unsere Wegpunkte setzen können 🙂

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert