✅ Noticias, temas, complementos de WEB y WordPress. Aquí compartimos consejos y las mejores soluciones para sitios web.

Uso de opciones para almacenar datos en el editor de bloques de WordPress (Gutenberg)

21

Anteriormente exploramos el almacenamiento de datos del editor de bloques de WordPress (Gutenberg) en los atributos de bloque y en la publicación meta, pero ¿sabía que puede almacenar y recuperar desde la tabla de opciones de WordPress importando apidesde @wordpress/api.

En esta guía, echamos un vistazo a lo que escribirías clásicamente en PHP como update_optiony get_option.

Para implementar esto, debemos aprovechar el ciclo de vida de React, por lo que veremos cómo crear un componente de React importando Componentdesde @wordpress/element.

requisitos previos

Ese último requisito es útil para la interfaz de usuario que vamos a usar en esta guía; sin embargo, en aplicaciones del mundo real, es probable que use este método en una barra lateral o en una página de opciones.

Registrar las Opciones en PHP

Antes de que podamos usar una opción en JavaScript, debemos asegurarnos de que la hayamos registrado en PHP usando register_settingy que el show_in_restargumento se haya establecido en verdadero.

Siguiendo con la guía de Dynamic Block, abra el archivo PHP raíz del complemento (en este caso wholesome-plugin.php) y agregue el siguiente código al final de ese archivo después de todas las demás funciones:

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

Este código registra un metacampo llamado wholesomecode_wholesome_plugin_block_textpara el wholesomecode_wholesome_plugin_settingsgrupo de opciones. También garantiza que la API REST pueda acceder a este metacampo con el show_in_restvalor establecido en verdadero.

Crear el componente

Abra el /src/edit.jsarchivo, vamos a alterar un poco la estructura de este archivo para que podamos generar nuestro archivo Component.

Corte y pegue la totalidad de este bloque de código en el /src/edit.jsarchivo, cubriremos lo que hace en 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>
    );
}

Puede reconocer que la interfaz de usuario que hemos implementado es exactamente la misma de la guía Gutenberg Meta Box, donde usamos meta atributos de publicación. También puede notar que todavía no estamos obteniendo o configurando información usando opciones, y en su lugar solo estamos usando el componente state.

Estado de uso

La razón por la que creamos un componente personalizado y luego lo pasamos a nuestra Editfunción es para que podamos aprovechar el estado. Hemos hecho esto porque:

  • Crearemos una función para cargar las opciones de la API, y debemos almacenar esto en el estado para que nuestros componentes puedan leerlo.
  • No queremos que la API actualice las opciones tan pronto como cambie el texto en nuestro cuadro de texto, por lo que necesitamos una función para guardar el estado en las opciones a través de la API una vez que se haya guardado la publicación.

Usar el estado es bastante simple. En el constructor inicializamos el estado así:

this.state = { exampleText: '' };

Y en el componente accedemos a él de forma similar a como hemos accedido a los atributos en la guía anterior:

const { exampleText } = this.state;

La diferencia es que, en nuestro onChangemétodo, en lugar de usar setAttributes, usamos this.setState.

Obtener opciones de la API

En la parte superior del documento importar apidesde @wordpress/api:

import api from '@wordpress/api';

Agregue una nueva propiedad donde se inicializa el estado de isAPILoaded. Necesitaremos esto para asegurarnos de que no intentamos acceder a la API o renderizar el componente antes de que se haya cargado la API.

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

Ahora dentro del Componente que creamos, agregue un bloque de código bajo el constructor llamado componentDidMount. Este es un método de ciclo de vida de React, que se llama después de que se ha agregado un componente al DOM.

En ese bloque de código agregue lo siguiente:

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

Aquí estamos accediendo a la opción que registramos anteriormente con la register_settingfunción.

Este bloque de código hace lo siguiente:

  • Obtiene la configuración de la API de configuración de Guttenberg de WordPress.
  • Obtiene isAPILoadeddel estado
  • Si la API no se ha cargado, obtiene la configuración de la API en unresponse
  • Luego configuramos el estado para actualizar el estado con la opción a la que queremos acceder y establecemos el isAPILoadedestado en verdadero

Detener la representación de bloques sin configuración

No queremos que nuestro bloque se represente antes de que se hayan completado las configuraciones. Para encargarnos de esto, podemos importar un PlaceHolder y un Spinner desde $wordpress/components:

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

Luego, en el método de representación del componente, asegúrese de obtener isAPILoadeddel estado y genere el Placeholdery Spinnersi no es así:

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

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

De esta forma, si las opciones no se han cargado, obtenemos un bonito marcador de posición hasta que se carga el componente:

Marcador de posición y Spinner

Conexión con Gutenberg en Save

Ahora que estamos leyendo las opciones de la tabla de opciones, necesitamos una forma de guardar esas opciones cuando las cambiamos. Para ello vamos al subscribealmacén de datos de WordPress Gutenberg, que nos indicará cuando algo haya cambiado.

Al usar esto, crearemos un oyente para cuando se guarde la publicación y guardaremos nuestra configuración cuando eso suceda.

Para ello importa subscribey selectdesde @wordpress/data.

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

Luego, en la parte superior del componentDidMountbloque de código, escribe lo siguiente:

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

El código hace lo siguiente:

  • Comprueba si la publicación se está guardando
  • Verifique si el guardado es un guardado automático
  • Si la publicación se está guardando y no se guarda automáticamente, inserte la nueva configuración en la API de configuración
  • Active un guardado de la API de configuración.

Un pequeño truco

Podríamos dejar nuestro código así, pero debido a que estamos colocando nuestra configuración en un bloque, y no en una barra lateral u otro componente del editor, si cambiamos una de las opciones, y nada más en el editor, el botón ‘guardar’ no volverse activo.

Esto se debe a que no estamos usando setAttributesni nada para alterar el código real del bloque.

Podemos solucionar esto simplemente editando otra parte de la publicación o agregando un pequeño truco en el TextControlcódigo:

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

Recordando poner esta línea de código en la parte superior del método de renderizado para extraer setAttributesdel props(debido a que estamos usando un Componente, accedemos a los accesorios ligeramente diferentes con this.

const { setAttributes } = this.props;

Ahora, cuando cambiamos nuestro atributo, un atributo ‘falso’ cambiará, lo que hará que el editor piense que ahora podemos guardar la publicación.

Es un poco raro, pero para este caso de uso hace lo que necesitamos.

EditEl código completo

Aquí está todo el código que necesita para el Editmétodo:

yo ` import {} de ‘ @wordpress /i18n’; importar api desde ‘ @wordpress /api’; importar { useBlockProps } desde ‘ @wordpress /block-editor’; import { Panel, PanelBody, Placeholder, Spinner, TextControl, } from ‘ @wordpress /components’; importar { seleccionar, suscribirse } desde ‘ @wordpress /data’; importar {Componente} desde ‘ @wordpress /element’;

importar ‘./editor.scss’;

clase OpcionesEjemplo extiende Componente { constructor() { super( …argumentos );

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

}

Exportar función predeterminada Editar (accesorios) { volver (

); }


### 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 ($atributos, $contenido) { $example_text = get_option( ‘wholesomecode_wholesome_plugin_example_text’ ); return "

$ejemplo_texto

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

importar {} de ‘ @wordpress /i18n’; importar api desde ‘ @wordpress /api’; importar { useBlockProps } desde ‘ @wordpress /block-editor’; import { Panel, PanelBody, PanelRow, Placeholder, SelectControl, Spinner, TextControl, ToggleControl, } from ‘ @wordpress /components’; importar { seleccionar, suscribirse } desde ‘ @wordpress /data’; importar {Componente} desde ‘ @wordpress /element’;

importar ‘./editor.scss’;

clase OpcionesEjemplo extiende Componente { constructor() { super( …argumentos );

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

}

Exportar función predeterminada Editar (accesorios) { volver (

); } `

Aquí está el resultado:

Uso de opciones para almacenar datos en el editor de bloques de WordPress (Gutenberg)Opciones adicionales

Fuente de grabación: 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