✅ Notizie, temi, plugin WEB e WordPress. Qui condividiamo suggerimenti e le migliori soluzioni per siti web.

Utilizzo delle opzioni per archiviare i dati nell’editor blocchi di WordPress (Gutenberg)

21

In precedenza abbiamo esplorato la memorizzazione dei dati dell’editor di blocchi di WordPress (Gutenberg) negli attributi di blocco e in post meta, ma sapevi che puoi archiviare e recuperare dalla tabella delle opzioni di WordPress importando apida @wordpress/api.

In questa guida diamo un’occhiata a cosa scriveresti classicamente in PHP come update_optione get_option.

Per implementarlo, dobbiamo sfruttare il ciclo di vita di React, quindi cercheremo di creare un componente React importando Componentda @wordpress/element.

Prerequisiti

Quest’ultimo requisito è utile per l’interfaccia utente che utilizzeremo in questa guida, tuttavia nelle applicazioni del mondo reale è probabile che tu utilizzi questo metodo in una barra laterale o nella pagina delle opzioni.

Registra le Opzioni in PHP

Prima di poter utilizzare un’opzione in JavaScript, dobbiamo assicurarci di averla registrata in PHP utilizzando register_settinge che l’ show_in_restargomento sia stato impostato su true.

Seguendo la guida al blocco dinamico, apri il file PHP radice del plugin (in questo caso wholesome-plugin.php) e aggiungi il seguente codice in fondo a quel file dopo tutte le altre funzioni:

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

Questo codice registra un meta campo chiamato wholesomecode_wholesome_plugin_block_textper il wholesomecode_wholesome_plugin_settingsgruppo di opzioni. Garantisce inoltre che l’API REST possa accedere a questo meta campo con il show_in_restvalore impostato su true.

Crea il componente

Apri il /src/edit.jsfile, modificheremo in qualche modo la struttura di questo file in modo da poter produrre il nostro file Component.

Taglia e incolla l’intero blocco di codice nel /src/edit.jsfile, tratteremo ciò che fa in un momento:

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

Potresti riconoscere che l’interfaccia utente che abbiamo messo in atto è esattamente la stessa della guida Gutenberg Meta Box, in cui abbiamo utilizzato gli attributi post meta. Potresti anche notare che non stiamo ancora ricevendo o impostando informazioni usando le opzioni, e invece stiamo solo usando il componente state.

Usando lo stato

Il motivo per cui abbiamo creato un componente personalizzato e poi lo abbiamo passato alla nostra Editfunzione è che possiamo sfruttare lo stato. Lo abbiamo fatto perché:

  • Creeremo una funzione per caricare le opzioni dall’API e dobbiamo memorizzarla nello stato in modo che i nostri componenti possano leggerla
  • Non vogliamo che l’API aggiorni le opzioni non appena il testo cambia nella nostra casella di testo, quindi abbiamo bisogno di una funzione per salvare lo stato nelle opzioni tramite l’API una volta che il post è stato salvato

Usare lo stato è piuttosto semplice. Nel costruttore inizializziamo lo stato in questo modo:

this.state = { exampleText: '' };

E nel componente accediamo in modo simile a come abbiamo avuto accesso agli attributi nella guida precedente:

const { exampleText } = this.state;

La differenza è che, sul nostro onChangemetodo, invece di utilizzare setAttributesutilizziamo this.setState.

Ottenere le opzioni dall’API

Nella parte superiore del documento importa apida @wordpress/api:

import api from '@wordpress/api';

Aggiungi una nuova proprietà in cui viene inizializzato lo stato di isAPILoaded. Avremo bisogno di questo per assicurarci di non tentare di accedere all’API o di eseguire il rendering del componente prima che l’API sia stata caricata.

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

Ora all’interno del Component che abbiamo creato, aggiungi un blocco di codice sotto il costruttore chiamato componentDidMount. Questo è un metodo del ciclo di vita React, che viene chiamato dopo che un componente è stato aggiunto al DOM.

In quel blocco di codice aggiungi quanto segue:

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

Qui accediamo all’opzione che abbiamo registrato in precedenza con la register_settingfunzione.

Questo blocco di codice esegue le seguenti operazioni:

  • Ottiene le impostazioni dall’API delle impostazioni Guttenberg di WordPress.
  • Ottiene isAPILoadeddallo stato
  • Se l’API non è stata caricata, recupera le Impostazioni dall’API in aresponse
  • Quindi impostiamo lo stato per aggiornare lo stato con l’opzione a cui vogliamo accedere e impostiamo lo isAPILoadedstato su true

Arresta il rendering del blocco senza impostazioni

Non vogliamo che il nostro blocco venga visualizzato prima che le impostazioni siano state popolate. Per occuparci di questo possiamo importare un PlaceHolder e uno Spinner da $wordpress/components:

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

Quindi nel metodo di rendering del componente, assicurati di ottenere isAPILoadeddallo stato e emetti Placeholdere Spinnerse non lo è:

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

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

In questo modo, se le opzioni non sono state caricate, otteniamo un bel segnaposto fino al caricamento del componente:

Segnaposto e Spinner

Entrare in Gutenberg su Save

Ora che stiamo leggendo le opzioni dalla tabella delle opzioni, abbiamo bisogno di un modo per salvare quelle opzioni quando le cambiamo. Per fare ciò andremo al subscribedatastore di WordPress Gutenberg, che indicherà quando qualcosa è cambiato.

Usando questo creeremo un listener per quando il post verrà salvato e salveremo le nostre impostazioni quando ciò accade.

Per fare questo importare subscribee selectda @wordpress/data.

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

Quindi nella parte superiore del componentDidMountblocco di codice, scrivi quanto segue:

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

Il codice esegue le seguenti operazioni:

  • Verifica se il post viene salvato
  • Verifica se il salvataggio è automatico
  • Se il post sta salvando e non è un salvataggio automatico, inserisci le nuove impostazioni nell’API delle impostazioni
  • Attiva un salvataggio dell’API delle impostazioni.

Un piccolo trucco

Potremmo lasciare il nostro codice in questo modo, ma poiché stiamo mettendo le nostre impostazioni in un blocco e non in una barra laterale o in un altro componente dell’editor, se cambiamo una delle opzioni e nient’altro nell’editor, il pulsante ‘salva’ non lo fa diventare attivo.

Questo perché non stiamo usando setAttributeso altro per alterare il codice effettivo del blocco.

Possiamo aggirare questo problema, semplicemente modificando un’altra parte del post o aggiungendo un piccolo hack nel TextControlcodice:

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

Ricordandoci di mettere questa riga di codice all’inizio del metodo render da estrarre setAttributesda props(perché stiamo usando un Component a cui accediamo a prop leggermente diversi con this.

const { setAttributes } = this.props;

Ora, quando cambiamo il nostro attributo, un attributo "falso" cambierà, facendo pensare all’editor che ora possiamo salvare il post.

È un po’ complicato, ma per questo caso d’uso fa ciò di cui abbiamo bisogno.

L’intero Editcodice

Ecco tutto il codice necessario per il Editmetodo:

io ` import {} da ‘ @wordpress /i18n’; importa API da ‘ @wordpress /api’; importa {useBlockProps} da ‘ @wordpress /block-editor’; import {Pannello, PanelBody, Placeholder, Spinner, TextControl, } da ‘ @wordpress /components’; importa {seleziona, iscriviti} da ‘ @wordpress /data’; importa {Componente} da ‘ @wordpress /elemento’;

importa ‘./editor.scss’;

class OptionsExample estende 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>) }

}

funzione di esportazione predefinita Modifica( 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’ = > funzione($attributi, $contenuto) { $example_text = get_option( ‘wholesomecode_wholesome_plugin_example_text’); return "

$testo_esempio

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

importa {} da ‘ @wordpress /i18n’; importa API da ‘ @wordpress /api’; importa {useBlockProps} da ‘ @wordpress /block-editor’; import {Pannello, PanelBody, PanelRow, Placeholder, SelectControl, Spinner, TextControl, ToggleControl, } da ‘ @wordpress /components’; importa {seleziona, iscriviti} da ‘ @wordpress /data’; importa {Componente} da ‘ @wordpress /elemento’;

importa ‘./editor.scss’;

class OptionsExample estende 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>) }

}

funzione di esportazione predefinita Modifica( props) { return (

); } `

Ecco il risultato:

Utilizzo delle opzioni per archiviare i dati nell'editor blocchi di WordPress (Gutenberg)Opzioni extra

Fonte di registrazione: wholesomecode.ltd

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More