✅ WEB і WordPress новини, теми, плагіни. Тут ми ділимося порадами і кращими рішеннями для сайтів.

Використання параметрів для зберігання даних у редакторі блоків WordPress (Gutenberg)

16

Раніше ми досліджували можливість зберігання даних редактора блоків WordPress (Gutenberg) в атрибутах блоку та мета публікації, але чи знаєте ви, що ви можете зберігати та отримувати дані в таблиці параметрів WordPress, імпортуючи apiз @wordpress/api.

У цьому посібнику ми розглянемо те, що ви б класично написали в PHP як update_optionі get_option.

Щоб реалізувати це, нам потрібно скористатися перевагами життєвого циклу React, тому ми розглянемо створення компонента React шляхом імпорту Componentз @wordpress/element.

передумови

Ця остання вимога є корисною для інтерфейсу користувача, який ми збираємося використовувати в цьому посібнику, однак у реальних програмах ви, ймовірно, використаєте цей метод на бічній панелі або сторінці параметрів.

Зареєструйте параметри в PHP

Перш ніж ми зможемо використовувати опцію в JavaScript, ми повинні переконатися, що ми зареєстрували її в PHP за допомогою register_setting, і що для show_in_restаргументу встановлено значення true.

Дотримуючись посібника Dynamic Block, відкрийте кореневий файл PHP плагіна (в даному випадку wholesome-plugin.php) і додайте наступний код у нижню частину цього файлу після всіх інших функцій:

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

Цей код реєструє мета-поле, що викликається wholesomecode_wholesome_plugin_block_textдля wholesomecode_wholesome_plugin_settingsгрупи параметрів. Це також гарантує, що REST API може отримати доступ до цього мета-поля зі show_in_restзначенням, яке має значення true.

Створіть компонент

Відкрийте /src/edit.jsфайл, ми збираємося дещо змінити структуру цього файлу, щоб ми могли вивести наш Component.

Виріжте та вставте весь цей блок коду у /src/edit.jsфайл, ми розповімо, що він робить за мить:

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

Ви можете впізнати, що користувальницький інтерфейс, який ми створили, точно такий самий, як у посібнику Gutenberg Meta Box, де ми використовували мета-атрибути публікації. Ви також можете помітити, що ми поки що не отримуємо та не встановлюємо інформацію за допомогою параметрів, а замість цього ми просто використовуємо компонент state.

Використання стану

Причина, по якій ми створили спеціальний компонент, а потім передали його в нашу Editфункцію, полягає в тому, щоб ми могли скористатися перевагами стану. Ми зробили це тому, що:

  • Ми створимо функцію для завантаження параметрів з API, і нам потрібно зберегти її в стані, щоб наші компоненти могли її читати
  • Ми не хочемо, щоб API оновлював параметри, щойно змінюється текст у нашому текстовому полі, тому нам потрібна функція для збереження стану в параметрах через API після збереження публікації

Використання стану досить просте. У конструкторі ми ініціалізуємо стан так:

this.state = { exampleText: '' };

І в компоненті ми отримуємо доступ до нього так само, як ми отримували доступ до атрибутів у попередньому посібнику:

const { exampleText } = this.state;

Різниця полягає в тому, що в нашому onChangeметоді замість використання setAttributesми використовуємо this.setState.

Отримання параметрів з API

У верхній частині документа імпортувати apiз @wordpress/api:

import api from '@wordpress/api';

Додайте нову властивість, де ініціалізується стан isAPILoaded. Це нам знадобиться, щоб переконатися, що ми не намагаємося отримати доступ до API або відобразити компонент до того, як API завантажиться.

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

Тепер до створеного нами компонента додайте блок коду під конструктор під назвою componentDidMount. Це метод життєвого циклу React, який викликається після додавання компонента до DOM.

У цей блок коду додайте наступне:

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

Тут ми отримуємо доступ до параметра, який ми зареєстрували раніше за допомогою register_settingфункції.

Цей блок коду робить наступне:

  • Отримує налаштування з WordPress Guttenberg Settings API.
  • Отримує isAPILoadedвід сат
  • Якщо API не було завантажено, він отримує налаштування з API в aresponse
  • Потім ми встановлюємо стан, щоб оновити стан за допомогою опції, до якої ми хочемо отримати доступ, і встановлюємо isAPILoadedстан на true

Зупиніть візуалізацію блоку без налаштувань

Ми не хочемо, щоб наш блок рендерився до того, як параметри будуть заповнені. Щоб подбати про це, ми можемо імпортувати PlaceHolder і Spinner з $wordpress/components:

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

Потім у методі рендерингу компонента переконайтеся, що ви отримали isAPILoadedвід стану, і виведіть Placeholderі, Spinnerякщо він не має:

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

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

Таким чином, якщо параметри не завантажено, ми отримаємо гарний заповнювач, доки компонент не завантажиться:

Заповнювач і Spinner

Підключення до Gutenberg on Save

Тепер, коли ми читаємо параметри з таблиці параметрів, нам потрібен спосіб зберегти ці параметри, коли ми їх змінюємо. Для цього ми перейдемо до subscribeсховища даних WordPress Gutenberg, яке вказуватиме, коли щось змінилося.

Використовуючи це, ми створимо слухач, коли публікація буде збережена, і збережемо наші налаштування, коли це станеться.

Для цього імпортуйте subscribeта selectз @wordpress/data.

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

Потім у верхній частині 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 налаштувань
  • Запустити збереження API налаштувань.

Невеликий хак

Ми могли б залишити наш код таким, але оскільки ми розміщуємо наші налаштування в блоці, а не на бічній панелі чи іншому компоненті редактора, якщо ми змінюємо один із параметрів і нічого іншого в редакторі, кнопка «зберегти» не працюватиме стати активним.

Це тому, що ми не використовуємо setAttributesі не змінюємо фактичний код блоку.

Ми можемо обійти це, просто відредагувавши іншу частину публікації, або додавши невеликий хак у TextControlкод:

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

Не забувайте розмістити цей рядок коду на початку методу рендерингу, щоб витягти setAttributesйого з props(оскільки ми використовуємо компонент, ми отримуємо дещо інший доступ до атрибутів за допомогою this.

const { setAttributes } = this.props;

Тепер, коли ми змінюємо наш атрибут, змінюється атрибут «фальшивий», через що редактор думає, що тепер ми можемо зберегти публікацію.

Він трохи хакерський, але для цього випадку використання він робить те, що нам потрібно.

Весь Editкод

Ось увесь код, потрібний для Editметоду:

i ` import {} з ‘ @wordpress /i18n’; імпортувати API з ‘ @wordpress /api’; імпорт { useBlockProps } з ‘ @wordpress /block-editor’; import { Panel, PanelBody, Placeholder, Spinner, TextControl, } from ‘ @wordpress /components’; import { select, subscribe } from ‘ @wordpress /data’; імпортувати { Компонент } з ‘ @wordpress /element’;

імпорт ‘./editor.scss’;

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

}

експорт функції за замовчуванням 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 "

$example_text

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

імпорт {} з ‘ @wordpress /i18n’; імпортувати API з ‘ @wordpress /api’; імпорт { useBlockProps } з ‘ @wordpress /block-editor’; імпорт { Panel, PanelBody, PanelRow, Placeholder, SelectControl, Spinner, TextControl, ToggleControl, } з ‘ @wordpress /components’; import { select, subscribe } from ‘ @wordpress /data’; імпортувати { Компонент } з ‘ @wordpress /element’;

імпорт ‘./editor.scss’;

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

}

експорт функції за замовчуванням Edit( props) { return (

); } `

Ось результат:

Використання параметрів для зберігання даних у редакторі блоків WordPress (Gutenberg)Додаткові параметри

Джерело запису: wholesomecode.ltd

Цей веб -сайт використовує файли cookie, щоб покращити ваш досвід. Ми припустимо, що з цим все гаразд, але ви можете відмовитися, якщо захочете. Прийняти Читати далі