✅ WEB- und WordPress-Nachrichten, Themen, Plugins. Hier teilen wir Tipps und beste Website-Lösungen.

Verwenden von Optionen zum Speichern von Daten im WordPress-Blockeditor (Gutenberg)

13

Wir haben zuvor das Speichern von WordPress-Blockeditor-Daten (Gutenberg) in Blockattributen und in Post-Meta untersucht, aber wussten Sie, dass Sie in der WordPress-Optionstabelle speichern und abrufen können, indem Sie apiaus importieren @wordpress/api.

In diesem Leitfaden werfen wir einen Blick darauf, was Sie klassisch in PHP als update_optionund schreiben würden get_option.

Um dies zu implementieren, müssen wir den React-Lebenszyklus nutzen, also werden wir uns mit dem Erstellen einer React-Komponente durch Importieren Componentaus @wordpress/element.

Voraussetzungen

Diese letzte Anforderung ist für die Benutzeroberfläche nützlich, die wir in diesem Handbuch verwenden werden. In realen Anwendungen ist es jedoch wahrscheinlich, dass Sie diese Methode in einer Seitenleiste oder Optionsseite verwenden würden.

Registrieren Sie die Optionen in PHP

Bevor wir eine Option in JavaScript verwenden können, müssen wir sicherstellen, dass wir sie in PHP mit registriert haben register_settingund dass das show_in_restArgument auf wahr gesetzt wurde.

Öffnen Sie im Anschluss an die Dynamic Block-Anleitung die Root-PHP-Datei des Plugins (in diesem Fall wholesome-plugin.php) und fügen Sie nach allen anderen Funktionen den folgenden Code am Ende dieser Datei hinzu:

function wholesomecode_wholesome_plugin_register_settings() {
    register_setting(
        'wholesomecode_wholesome_plugin_settings',
        'wholesomecode_wholesome_plugin_example_text',
        [
            'default'       => '',
            'show_in_rest'  => true,
            'type'          => 'string',
        ]
    );
}
add_action( 'init', 'wholesomecode_wholesome_plugin_register_settings' );

Dieser Code registriert ein Metafeld, das wholesomecode_wholesome_plugin_block_textfür die wholesomecode_wholesome_plugin_settingsOptionsgruppe aufgerufen wird. Es stellt auch sicher, dass die REST-API auf dieses Metafeld zugreifen kann, wobei der show_in_restWert auf „true“ gesetzt ist.

Erstellen Sie die Komponente

Öffnen Sie die /src/edit.jsDatei, wir werden die Struktur dieser Datei etwas ändern, damit wir unsere Component.

Schneiden Sie den gesamten Codeblock aus und fügen Sie ihn in die /src/edit.jsDatei ein. Wir werden gleich behandeln, was er tut:

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import {
    Panel,
    PanelBody,
    TextControl,
} from '@wordpress/components';
import { Component } from '@wordpress/element';

import './editor.scss';

class OptionsExample extends Component {
    constructor() {
        super( ...arguments );
        this.state = { exampleText: '' };
    }

    render() {
        const { exampleText } = this.state;
        return (<Panel>
                <PanelBody
                    title={ __( 'Example Meta Box', 'wholesome-plugin') }
                    icon="admin-plugins"
                >
                    <TextControl
                        help={ __( 'This is an example text field.', 'wholesome-plugin') }
                        label={ __( 'Example Text', 'wholesome-plugin') }
                        onChange={ (exampleText) => this.setState( { exampleText }) }
                        value={ exampleText }
                    />
                </PanelBody>
            </Panel>) }
}

export default function Edit( props) {
    return (<div { ...useBlockProps() }>
            <OptionsExample { ...props }/>
        </div>
    );
}

Sie können erkennen, dass die von uns eingerichtete Benutzeroberfläche genau die gleiche ist wie im Gutenberg Meta Box – Leitfaden, in der wir Post-Meta-Attribute verwendet haben. Möglicherweise stellen Sie auch fest, dass wir Informationen noch nicht mithilfe von Optionen abrufen oder festlegen und stattdessen nur die Komponente verwenden state.

Zustand verwenden

Der Grund, warum wir eine benutzerdefinierte Komponente erstellt und diese dann an unsere EditFunktion übergeben haben, ist, dass wir den Status nutzen können. Wir haben dies getan, weil:

  • Wir werden eine Funktion erstellen, um die Optionen aus der API zu laden, und wir müssen diese im Zustand speichern, damit unsere Komponenten sie lesen können
  • Wir möchten nicht, dass die API die Optionen aktualisiert, sobald sich der Text in unserem Textfeld ändert, daher benötigen wir eine Funktion, um den Status in den Optionen über die API zu speichern, sobald der Beitrag gespeichert wurde

Die Verwendung von state ist ziemlich einfach. Im Konstruktor initialisieren wir den Zustand wie folgt:

this.state = { exampleText: '' };

Und in der Komponente greifen wir darauf ähnlich zu, wie wir im vorherigen Handbuch auf Attribute zugegriffen haben:

const { exampleText } = this.state;

Der Unterschied besteht darin, dass wir bei unserer onChangeMethode .setAttributes``this.setState

Abrufen von Optionen von der API

Oben im Dokumentenimport apivon @wordpress/api:

import api from '@wordpress/api';

Fügen Sie eine neue Eigenschaft hinzu, in der der Zustand von initialisiert wird isAPILoaded. Wir benötigen dies, um sicherzustellen, dass wir nicht versuchen, auf die API zuzugreifen oder die Komponente zu rendern, bevor die API geladen wurde.

this.state = {
  exampleText: '',
  isAPILoaded: false,
};

Fügen Sie nun innerhalb der von uns erstellten Komponente einen Codeblock unter dem Konstruktor mit dem Namen hinzu componentDidMount. Dies ist eine React-Lebenszyklusmethode, die aufgerufen wird, nachdem eine Komponente zum DOM hinzugefügt wurde.

Fügen Sie in diesem Codeblock Folgendes hinzu:

componentDidMount() {
  api.loadPromise.then(() => {
    this.settings = new api.models.Settings();

    const { isAPILoaded } = this.state;

    if (isAPILoaded === false) {
      this.settings.fetch().then( (response) => {
        this.setState( {
          exampleText: response[ 'wholesomecode_wholesome_plugin_example_text' ],
          isAPILoaded: true,
        } );
      } );
    }
  } );
}

Hier greifen wir auf die Option zu, die wir zuvor mit der register_settingFunktion registriert haben.

Dieser Codeblock bewirkt Folgendes:

  • Ruft die Einstellungen von der WordPress Guttenberg Settings API ab.
  • Kommt isAPILoadedvom Staat
  • Wenn die API nicht geladen wurde, ruft sie die Einstellungen von der API in a abresponse
  • Wir setzen dann den Status, um den Status mit der Option zu aktualisieren, auf die wir zugreifen möchten, und setzen den isAPILoadedStatus auf „true „.

Stoppen Sie das Block-Rendering ohne Einstellungen

Wir möchten nicht, dass unser Block gerendert wird, bevor die Einstellungen ausgefüllt wurden. Um dies zu erledigen, können wir einen PlaceHolder und einen Spinner importieren aus $wordpress/components:

import {
    Panel,
    PanelBody,
    Placeholder,
    Spinner,
    TextControl,
} from '@wordpress/components';

Stellen Sie dann in der Render-Methode der Komponente sicher, dass Sie isAPILoadedden Status erhalten, und geben Sie das aus, Placeholderund Spinnerwenn dies nicht der Fall ist:

const {
  exampleText,
  isAPILoaded,
} = this.state;

if (! isAPILoaded) {
  return (<Placeholder>
      <Spinner />
    </Placeholder>
  );
}

Wenn die Optionen nicht geladen wurden, erhalten wir auf diese Weise einen schönen Platzhalter, bis die Komponente geladen wird:

Platzhalter und Spinner

Sich bei Save in Gutenberg einklinken

Jetzt, da wir Optionen aus der Optionstabelle lesen, brauchen wir eine Möglichkeit, diese Optionen zu speichern, wenn wir sie ändern. Dazu gehen wir subscribezum WordPress Gutenberg-Datenspeicher, der anzeigt, wenn sich etwas geändert hat.

Auf diese Weise erstellen wir einen Listener für das Speichern des Beitrags und speichern unsere Einstellungen, wenn dies geschieht.

Importieren Sie dazu subscribeund selectaus @wordpress/data.

import { select, subscribe } from '@wordpress/data';

Schreiben Sie dann oben in den componentDidMountCodeblock Folgendes:

subscribe(() => {
  const { exampleText } = this.state;

  const isSavingPost = select('core/editor').isSavingPost();
  const isAutosavingPost = select('core/editor').isAutosavingPost();

  if (isAutosavingPost) {
    return;
  }

  if (! isSavingPost) {
    return;
  }

  const settings = new api.models.Settings( {
    [ 'wholesomecode_wholesome_plugin_example_text' ]: exampleText,
  } );
  settings.save();
});

Der Code macht folgendes:

  • Überprüft, ob der Beitrag gespeichert wird
  • Überprüfen Sie, ob es sich bei der Speicherung um eine automatische Speicherung handelt
  • Wenn der Beitrag gespeichert wird und es sich nicht um eine automatische Speicherung handelt, übertragen Sie die neuen Einstellungen in die Einstellungs-API
  • Lösen Sie eine Speicherung der Einstellungs-API aus.

Ein kleiner Hack

Wir könnten unseren Code so belassen, aber da wir unsere Einstellungen in einen Block und nicht in eine Seitenleiste oder eine andere Editorkomponente einfügen, ändert sich die Schaltfläche „Speichern“ nicht, wenn wir eine der Optionen ändern und sonst nichts im Editor aktiv werden.

Dies liegt daran, dass wir setAttributesoder nichts verwenden, um den tatsächlichen Code des Blocks zu ändern.

Wir können dies umgehen, indem wir entweder einfach einen anderen Teil des Beitrags bearbeiten oder indem wir einen kleinen Hack in den TextControlCode einfügen:

onChange={ (exampleText) => { this.setState( { exampleText } ); setAttributes( { exampleText }) } }

Denken Sie daran, diese Codezeile an den Anfang der Render-Methode zu setzen, um sie setAttributesaus der zu extrahieren props(da wir eine Komponente verwenden, greifen wir mit etwas anders auf Props zu this.

const { setAttributes } = this.props;

Wenn wir jetzt unser Attribut ändern, wird sich ein „falsches“ Attribut ändern, sodass der Redakteur denkt, wir könnten den Beitrag jetzt speichern.

Es ist ein wenig hacky, aber für diesen Anwendungsfall tut es, was wir brauchen.

Der gesamte EditCode

EditHier ist der gesamte Code, den Sie für die Methode benötigen :

ich ` importiere {} von ‚ @wordpress /i18n‘; API aus ‚ @wordpress /api‘ importieren; import { useBlockProps } from ‚ @wordpress /block-editor‘; import { Panel, PanelBody, Placeholder, Spinner, TextControl, } from ‚ @wordpress /components‘; importiere { auswähle, abonniere } aus ‚ @wordpress /data‘; {Komponente} aus ‚ @wordpress /element‘ importieren;

import ‚./editor.scss‘;

Klasse OptionenBeispiel erweitert Komponente { Konstruktor () { super (… Argumente );

    this.state = {
        exampleText: '',
        isAPILoaded: false,
    };
}

componentDidMount() {

    subscribe( () => {
        const { exampleText } = this.state;

        const isSavingPost = select('core/editor').isSavingPost();
        const isAutosavingPost = select('core/editor').isAutosavingPost();

        if (isAutosavingPost) {
            return;
        }

        if (! isSavingPost) {
            return;
        }

        const settings = new api.models.Settings( {
            [ 'wholesomecode_wholesome_plugin_example_text' ]: exampleText,
        } );
        settings.save();
    });

    api.loadPromise.then( () => {
        this.settings = new api.models.Settings();

        const { isAPILoaded } = this.state;

        if (isAPILoaded === false) {
            this.settings.fetch().then( (response) => {
                this.setState( {
                    exampleText: response[ 'wholesomecode_wholesome_plugin_example_text' ],
                    isAPILoaded: true,
                } );
            } );
        }
    } );
}

render() {
    const {
        exampleText,
        isAPILoaded,
    } = this.state;

    const { setAttributes } = this.props;

    if (! isAPILoaded) {
        return (<Placeholder>
                <Spinner />
            </Placeholder>
        );
    }

    return (<Panel>
            <PanelBody
                title={ __( 'Example Meta Box', 'wholesomecode') }
                icon="admin-plugins"
            >
                <TextControl
                    help={ __( 'This is an example text field.', 'wholesome-plugin') }
                    label={ __( 'Example Text', 'wholesome-plugin') }
                    onChange={ (exampleText) => { this.setState( { exampleText } ); setAttributes( { exampleText }) } }
                    value={ exampleText }
                />
            </PanelBody>
        </Panel>) }

}

Standardfunktion exportieren Edit( props) { return (

); }


### Remove the Attributes

Option up `src/index.js` and remove the attributes block that we placed there in the previous guides. We are not storing any attributes, the data will be pushed into and retrieved from the options table.

Render the Output

Because we have saved our attribute as settings in the WordPress options table, we could output this anywhere in WordPress using `get_option`:

get_option( ‚Wholesomecode_wholesome_plugin_block_text‘, " );


Continuing from the [Dynamic Block guide](https://wholesomecode.ltd/guides/php-render-block-wordpress-gutenberg/), let's see how we can access this attribute on the server side in PHP.

With this in mind, let’s update our `register_block_type` to output the option:

register_block_type( ‚wholesomecode/wholesome-plugin‘, array( ‚editor_script‘ => ‚wholesomecode-wholesome-plugin-block-editor‘, ‚editor_style‘ => ‚wholesomecode-wholesome-plugin-block-editor‘, ‚render_callback‘ = > function( $attributes, $content) { $example_text = get_option( ‚wholesomecode_wholesome_plugin_example_text‘ ); return "

$Beispieltext

"; }, ’style‘ => ‚wholesomecode-wholesome-plugin-block‘,) );


Note that we no longer need to register the `attributes` here, because we are only accessing the post meta field via the `get_post_meta` function.

5.  
Using the Block
--------------------

Putting it all together, let’s see the block in action:

![Using the block editor for settings and options](https:

Extra: Add Some More Fields
-----------------------------

In the extra steps of the Custom Meta Box guide, we added in some extra fields. Let’s update the `Edit` method to include those same fields (note that I have omitted the hack):

importieren {} von ‚ @wordpress /i18n‘; API aus ‚ @wordpress /api‘ importieren; import { useBlockProps } from ‚ @wordpress /block-editor‘; importiere { Panel, PanelBody, PanelRow, Platzhalter, SelectControl, Spinner, TextControl, ToggleControl, } aus ‚ @wordpress /components‘; importiere { auswähle, abonniere } aus ‚ @wordpress /data‘; {Komponente} aus ‚ @wordpress /element‘ importieren;

import ‚./editor.scss‘;

Klasse OptionenBeispiel erweitert Komponente { Konstruktor () { super (… Argumente );

    this.state = {
        exampleSelect: '',
        exampleText: '',
        exampleText2: '',
        exampleText3: '',
        exampleToggle: false,
        isAPILoaded: false,
    };
}

componentDidMount() {

    subscribe( () => {
        const {
            exampleSelect,
            exampleText,
            exampleText2,
            exampleText3,
            exampleToggle,
        } = this.state;

        const isSavingPost = select('core/editor').isSavingPost();
        const isAutosavingPost = select('core/editor').isAutosavingPost();

        if (isAutosavingPost) {
            return;
        }

        if (! isSavingPost) {
            return;
        }

        const settings = new api.models.Settings( {
            [ 'wholesomecode_wholesome_plugin_example_select' ]: exampleSelect,
            [ 'wholesomecode_wholesome_plugin_example_text' ]: exampleText,
            [ 'wholesomecode_wholesome_plugin_example_text_2' ]: exampleText2,
            [ 'wholesomecode_wholesome_plugin_example_text_3' ]: exampleText3,
            [ 'wholesomecode_wholesome_plugin_example_toggle' ]: exampleToggle,
        } );
        settings.save();
    });

    api.loadPromise.then( () => {
        this.settings = new api.models.Settings();

        const { isAPILoaded } = this.state;

        if (isAPILoaded === false) {
            this.settings.fetch().then( (response) => {
                this.setState( {
                    exampleSelect: response[ 'wholesomecode_wholesome_plugin_example_select' ],
                    exampleText: response[ 'wholesomecode_wholesome_plugin_example_text' ],
                    exampleText2: response[ 'wholesomecode_wholesome_plugin_example_text_2' ],
                    exampleText3: response[ 'wholesomecode_wholesome_plugin_example_text_3' ],
                    exampleToggle: Boolean( response[ 'wholesomecode_wholesome_plugin_example_toggle' ] ),
                    isAPILoaded: true,
                } );
            } );
        }
    } );
}

render() {
    const {
        exampleSelect,
        exampleText,
        exampleText2,
        exampleText3,
        exampleToggle,
        isAPILoaded,
    } = this.state;

    if (! isAPILoaded) {
        return (<Placeholder>
                <Spinner />
            </Placeholder>
        );
    }

    return (<Panel>
            <PanelBody
                title={ __( 'Example Meta Box', 'wholesome-plugin') }
                icon="admin-plugins"
            >
                <SelectControl
                    help={ __( 'An example dropdown field.', 'wholesome-plugin') }
                    label={ __( 'Example Select', 'wholesome-plugin') }
                    onChange={ (exampleSelect) => this.setState( { exampleSelect }) }
                    options={ [
                        {
                            label: __( 'Please Select...', 'wholesome-plugin' ),
                            value: '',
                        },
                        {
                            label: __( 'Option 1', 'wholesome-plugin' ),
                            value: 'option-1',
                        },
                        {
                            label: __( 'Option 2', 'wholesome-plugin' ),
                            value: 'option-2',
                        },
                    ] }
                    value={ exampleSelect }
                />
                <TextControl
                    help={ __( 'This is an example text field.', 'wholesome-plugin') }
                    label={ __( 'Example Text', 'wholesome-plugin') }
                    onChange={ (exampleText) => this.setState( { exampleText }) }
                    value={ exampleText }
                />
                <PanelRow>
                    <TextControl
                        help={ __( 'Use PanelRow to place controls inline.', 'wholesome-plugin') }
                        label={ __( 'Example Text 2', 'wholesome-plugin') }
                        onChange={ (exampleText2) => this.setState( { exampleText2 }) }
                        value={ exampleText2 }
                    />
                    <TextControl
                        help={ __( 'This control is inline.', 'wholesome-plugin') }
                        label={ __( 'Example Text 3', 'wholesome-plugin') }
                        onChange={ (exampleText3) => this.setState( { exampleText3 }) }
                        value={ exampleText3 }
                    />
                </PanelRow>
                <ToggleControl
                    checked={ exampleToggle }
                    help={ __( 'An example toggle.', 'wholesome-plugin') }
                    label={ __( 'Example Toggle', 'wholesome-plugin') }
                    onChange={ (exampleToggle) => this.setState( { exampleToggle }) }
                />
            </PanelBody>
        </Panel>) }

}

Standardfunktion exportieren Edit( props) { return (

); } `

Hier ist das Ergebnis:

Zusätzliche Optionen

Aufnahmequelle: wholesomecode.ltd

Diese Website verwendet Cookies, um Ihre Erfahrung zu verbessern. Wir gehen davon aus, dass Sie damit einverstanden sind, Sie können sich jedoch abmelden, wenn Sie möchten. Annehmen Weiterlesen