✅ WEB- och WordPress -nyheter, teman, plugins. Här delar vi tips och bästa webbplatslösningar.

Använda alternativ för att lagra data i WordPress Block Editor (Gutenberg)

16

Vi har tidigare utforskat lagring av WordPress-blockredigeringsdata (Gutenberg) i blockattribut och i postmeta, men visste du att du kan lagra och hämta från i WordPress-alternativtabellen genom att importera apifrån @wordpress/api.

I den här guiden tar vi en titt på vad du klassiskt skulle skriva i PHP som update_optionoch get_option.

För att implementera detta måste vi dra nytta av Reacts livscykel, så vi kommer att titta på att skapa en React-komponent genom att importera Componentfrån @wordpress/element.

Förutsättningar

Det sista kravet är användbart för det användargränssnitt som vi kommer att använda i den här guiden, men i verkliga applikationer är det troligt att du skulle använda den här metoden i en sidofält eller alternativsida.

Registrera alternativen i PHP

Innan vi kan använda ett alternativ i JavaScript måste vi se till att vi har registrerat det i PHP med hjälp av register_settingoch att show_in_restargumentet har satts till sant.

Följ upp guiden för Dynamic Block, öppna root-PHP-filen för plugin-programmet (i det här fallet wholesome-plugin.php) och lägg till följande kod längst ner i filen efter alla andra funktioner:

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' );

Denna kod registrerar ett metafält som kallas wholesomecode_wholesome_plugin_block_textför wholesomecode_wholesome_plugin_settingsalternativgruppen. Det säkerställer också att REST API kan komma åt detta metafält med show_in_restvärdet satt till sant.

Skapa komponenten

Öppna /src/edit.jsfilen, vi kommer att ändra strukturen på den här filen något så att vi kan mata ut vår Component.

Klipp ut och klistra in hela detta kodblock i /src/edit.jsfilen, vi kommer att täcka vad det gör på ett ögonblick:

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>
    );
}

Du kanske känner igen att användargränssnittet vi har infört är exakt samma från Gutenberg Meta Box -guiden, där vi använde post-metaattribut. Du kanske också märker att vi inte får eller ställer in information med alternativ ännu, utan istället använder vi bara komponenten state.

Använder staten

Anledningen till att vi har skapat en anpassad komponent och sedan överfört den till vår Editfunktion är så att vi kan dra fördel av staten. Vi har gjort detta för att:

  • Vi kommer att skapa en funktion för att ladda alternativen från API:t, och vi måste lagra detta i tillstånd så att våra komponenter kan läsa det
  • Vi vill inte att API uppdaterar alternativen så fort texten ändras i vår textruta, så vi behöver en funktion för att spara tillståndet i alternativen via API när inlägget har sparats

Att använda tillstånd är ganska enkelt. I konstruktorn initierar vi tillståndet så här:

this.state = { exampleText: '' };

Och i komponenten kommer vi åt den på samma sätt som vi har fått åtkomst till attribut i den tidigare guiden:

const { exampleText } = this.state;

Skillnaden är att på vår onChangemetod använder setAttributesvi istället för att använda this.setState.

Få alternativ från API

Överst i dokumentet importera apifrån @wordpress/api:

import api from '@wordpress/api';

Lägg till en ny egenskap där tillståndet initieras av isAPILoaded. Vi kommer att behöva detta för att se till att vi inte försöker komma åt API:et eller rendera komponenten innan API:et har laddats.

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

Nu i komponenten vi skapade, lägg till ett kodblock under konstruktorn som heter componentDidMount. Detta är en React-livscykelmetod, som anropas efter att en komponent har lagts till i DOM.

Lägg till följande i kodblocket:

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,
        } );
      } );
    }
  } );
}

Här kommer vi åt alternativet vi registrerade tidigare med register_settingfunktionen.

Detta kodblock gör följande:

  • Hämtar inställningarna från WordPress Guttenberg Settings API.
  • Får isAPILoadedfrån saten
  • Om API:et inte har laddats hämtar det inställningarna från API:et i enresponse
  • Vi ställer sedan in tillståndet för att uppdatera tillståndet med alternativet vi vill komma åt och ställer in isAPILoadedtillståndet till sant

Stoppa blockåtergivningen utan inställningar

Vi vill inte att vårt block ska renderas innan inställningarna har fyllts i. För att ta hand om detta kan vi importera en platshållare och en spinnare från $wordpress/components:

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

Sedan i komponentrenderingsmetoden, se till att du hämtar isAPILoadedfrån tillståndet och matar ut Placeholderoch Spinnerom det inte har:

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

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

På detta sätt, om alternativen inte har laddats, får vi en bra platshållare tills komponenten laddas:

Platshållare och Spinner

Hakar på Gutenberg på Spara

Nu när vi läser alternativ från alternativtabellen behöver vi ett sätt att spara dessa alternativ när vi ändrar dem. För att göra detta går vi subscribetill WordPress Gutenbergs datalager, som kommer att indikera när något har förändrats.

Med detta skapar vi en lyssnare för när inlägget sparas och sparar våra inställningar när det händer.

För att göra detta importera subscribeoch selectfrån @wordpress/data.

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

Skriv sedan följande överst i componentDidMountkodblocket:

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();
});

Koden gör följande:

  • Kontrollerar om inlägget sparas
  • Kontrollera om lagringen är en automatisk lagring
  • Om inlägget sparas och det inte är en autospara, tryck in de nya inställningarna i Settings API
  • Utlösa en lagring av Settings API.

Ett litet hack

Vi skulle kunna lämna vår kod så här, men eftersom vi lägger in våra inställningar i ett block, och inte i en sidofält eller annan redigeringskomponent, om vi ändrar ett av alternativen, och inget annat i redigeraren, fungerar inte "spara"-knappen bli aktiv.

Detta beror på att vi inte använder setAttributeseller något för att ändra den faktiska koden för blocket.

Vi kan komma runt detta genom att antingen, bara redigera en annan del av inlägget, eller genom att lägga till ett litet hack i TextControlkoden:

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

Kom ihåg att sätta denna kodrad överst i renderingsmetoden för att extrahera setAttributesfrån props(eftersom vi använder en komponent kommer vi åt rekvisita något annorlunda med this.

const { setAttributes } = this.props;

Nu när vi ändrar vårt attribut kommer ett "falskt" attribut att ändras, vilket gör att redaktören tror att vi nu kan spara inlägget.

Det är lite hackigt, men för det här användningsfallet gör det vad vi behöver.

Hela Editkoden

Här är all kod du behöver för Editmetoden:

i ` import {} från ’ @wordpress /i18n’; importera api från ’ @wordpress /api’; importera { useBlockProps } från ’ @wordpress /block-editor’; importera { Panel, PanelBody, Placeholder, Spinner, TextControl, } från ’ @wordpress /components’; importera { välj, prenumerera } från ’ @wordpress /data’; importera { Komponent } från ’ @wordpress /element’;

importera ’./editor.scss’;

class OptionsExample utökar Component { constructor() { super( …arguments );

    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>) }

}

export standardfunktion Redigera( rekvisita) { 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 "

$example_text

"; }, ’style’ => ’hälsokod-hälsosam-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):

importera {} från ’ @wordpress /i18n’; importera api från ’ @wordpress /api’; importera { useBlockProps } från ’ @wordpress /block-editor’; importera { Panel, PanelBody, PanelRow, Platshållare, SelectControl, Spinner, TextControl, ToggleControl, } från ’ @wordpress /components’; importera { välj, prenumerera } från ’ @wordpress /data’; importera { Komponent } från ’ @wordpress /element’;

importera ’./editor.scss’;

class OptionsExample utökar Component { constructor() { super( …arguments );

    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>) }

}

export standardfunktion Redigera( rekvisita) { return (

); } `

Här är resultatet:

Använda alternativ för att lagra data i WordPress Block Editor (Gutenberg)Extra alternativ

Inspelningskälla: wholesomecode.ltd

Denna webbplats använder cookies för att förbättra din upplevelse. Vi antar att du är ok med detta, men du kan välja bort det om du vill. Jag accepterar Fler detaljer