Crie um painel personalizador usando os componentes do WordPress Block Editor (Gutenberg)
Em nosso último guia, analisamos a criação de uma página de configurações usando os componentes do WordPress Block Editor (Gutenberg). Neste guia, iremos ainda mais longe e usaremos os componentes do Gutenberg dentro do WordPress Customizer.
O personalizador com componentes Gutenberg
Pré-requisitos
- Ter seguido o guia Criando um Plugin para o Editor de Blocos do WordPress (Gutenberg)
- Seguiu o guia Using Options to Store Data in the WordPress Block Editor (Gutenberg)
- Seguiu o guia Adicionar pontos de entrada ao WordPress Create Block Script
- Ter seguido o guia do componente Criar uma página de configurações usando o WordPress Block Editor (Gutenberg)
Criar um ponto de entrada no webpack
Seguindo o guia Adicionar pontos de entrada ao WordPress Create Block Script, crie um novo ponto de entrada no arquivo estendido webpack.config.jsque você criou nesse guia.
const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
const path = require( 'path' );
module.exports = {
...defaultConfig,
entry: {
...defaultConfig.entry,
customizer: path.resolve( process.cwd(), 'src', 'customizer.js' ),
}
};
Crie dois novos arquivos em sua solução:
/src/customizer.js/src/customizer.scss
Vamos usá-los para criar nosso plugin.
Registrar as configurações e componentes do personalizador em PHP
Seguindo os guias nos pré-requisitos, abra o arquivo PHP raiz do plugin (neste caso wholesome-plugin.php) e adicione o seguinte:
Registre o Controle do Personalizador
Precisamos criar um controle personalizado do Customizer. Adicione o seguinte código ao seu arquivo que renderizará uma chamada que gera o a <div>com um ID ao qual nosso JavaScript pode se conectar.
function wholesomecode_wholesome_plugin_customizer_register( $wp_customize) {
class Wholesome_Plugin_Gutenberg_Control extends WP_Customize_Control {
public $type = 'wholesome-plugin-gutenberg-control';
public function render_content() {}
public function content_template() {
?>
<div id="wholesome-plugin-customizer"></div>
<?php
}
}
$wp_customize->register_control_type( 'Wholesome_Plugin_Gutenberg_Control' );
}
add_action( 'customize_register', 'wholesomecode_wholesome_plugin_customizer_register', 10 );
Na parte inferior deste arquivo registramos o controle com o register_control_typeque nos permite acessar este controle em JavaScript.
Registre as configurações do personalizador
No mesmo bloco de código precisamos registrar as configurações que vamos usar no personalizador. Para fazer isso, adicione o seguinte bloco de código após a linha que faz o register_control_type.
$wp_customize->add_setting( 'wholesomecode_wholesome_plugin_example_select' );
$wp_customize->add_setting( 'wholesomecode_wholesome_plugin_example_text' );
$wp_customize->add_setting( 'wholesomecode_wholesome_plugin_example_text_2', [ 'type' => 'option' ] );
$wp_customize->add_setting( 'wholesomecode_wholesome_plugin_example_toggle', [ 'type' => 'option' ] );
Observe que as duas primeiras configurações estarão acessíveis por meio da get_theme_modfunção padrão, enquanto as duas últimas configurações passam os argumentos, o 'type' => 'option'que significa que essas configurações serão registradas como campos exclusivos na tabela de opções e estarão acessíveis via get_option.
Para essas duas configurações inferiores, precisamos garantir que elas sejam registradas via register_settinge show_in_restpara truecada uma, para que possam ser acessadas via Gutenberg.
Registre as configurações de ‘opção’
Registre as duas últimas configurações do personalizador (que acessaremos via get_option) com o seguinte bloco de código:
function wholesomecode_wholesome_plugin_register_settings() {
register_setting(
'wholesomecode_wholesome_plugin_settings',
'wholesomecode_wholesome_plugin_example_text_2',
[
'default' => '',
'show_in_rest' => true,
'type' => 'string',
]
);
register_setting(
'wholesomecode_wholesome_plugin_settings',
'wholesomecode_wholesome_plugin_example_toggle',
[
'default' => '',
'show_in_rest' => true,
'type' => 'string',
]
);
}
add_action( 'init', 'wholesomecode_wholesome_plugin_register_settings', 10 );
Enfileirar os scripts
Por fim, registre os ativos do personalizador com o código a seguir (consulte o guia Adicionar pontos de entrada para obter mais informações).
function wholesomecode_wholesome_plugin_customizer_scripts() {
$dir = __DIR__;
$script_asset_path = "$dir/build/customizer.asset.php";
if (! file_exists( $script_asset_path)) {
throw new Error(
'You need to run `npm start` or `npm run build` for the "wholesomecode/wholesome-plugin" block first.'
);
}
$customizer_js = 'build/customizer.js';
$script_asset = require( $script_asset_path );
wp_enqueue_script(
'wholesomecode-wholesome-plugin-customizer-editor',
plugins_url( $customizer_js, __FILE__ ),
$script_asset['dependencies'],
$script_asset['version']
);
wp_set_script_translations( 'wholesomecode-wholesome-plugin-block-editor', 'wholesome-plugin' );
wp_localize_script(
'wholesomecode-wholesome-plugin-customizer-editor',
'WholesomePluginSettings',
[
'wholesomecode_wholesome_plugin_example_select' => get_theme_mod( 'wholesomecode_wholesome_plugin_example_select', '' ),
'wholesomecode_wholesome_plugin_example_text' => get_theme_mod( 'wholesomecode_wholesome_plugin_example_text', '' ),
]
);
$customizer_css = 'build/customizer.css';
wp_enqueue_style(
'wholesomecode-wholesome-plugin-customizer',
plugins_url( $customizer_css, __FILE__ ),
['wp-components'],
filemtime( "$dir/$customizer_css") );
}
add_action( 'customize_controls_enqueue_scripts', 'wholesomecode_wholesome_plugin_customizer_scripts', 10 );
Observe que também usamos wp_localize_scriptneste bloco de código para passar as configurações que acessaremos get_theme_modpara o JavaScript.
Vamos dar uma olhada nesta parte do código com mais detalhes:
wp_localize_script(
'wholesomecode-wholesome-plugin-customizer-editor',
'WholesomePluginSettings',
[
'wholesomecode_wholesome_plugin_example_select' => get_theme_mod( 'wholesomecode_wholesome_plugin_example_select', '' ),
'wholesomecode_wholesome_plugin_example_text' => get_theme_mod( 'wholesomecode_wholesome_plugin_example_text', '' ),
]
);
Observe que estamos usando as mesmas chaves de configuração que registramos quando registramos as configurações do personalizador $wp_customize->add_settinganteriormente (as que não foram configuradas para usar uma opção).
Construir o painel do personalizador em JavaScript
Adicione o seguinte código no /src/customizer.jsarquivo.
Na maior parte, esse código (o Appcomponente) é um retrabalho do código do guia Criar página de configurações. Ele usa os mesmos componentes e ainda define o stateda API de Configurações, mas dispensa o botão salvar e a área de avisos.
import './customizer.scss';
const { api } = wp;
import {
Panel,
PanelBody,
Placeholder,
SelectControl,
Spinner,
TextControl,
ToggleControl,
} from '@wordpress/components';
import {
Fragment,
render,
Component,
} from '@wordpress/element';
import { __ } from '@wordpress/i18n';
const { customize } = wp;
class App extends Component {
constructor() {
super( ...arguments );
this.state = {
exampleSelect: '',
exampleText: '',
exampleText2: '',
exampleText3: '',
exampleToggle: false,
isAPILoaded: false,
};
}
componentDidMount() {
api.loadPromise.then(() => {
this.settings = new api.models.Settings();
const { isAPILoaded } = this.state;
if (isAPILoaded === false) {
this.settings.fetch().then( (response) => {
this.setState( {
exampleSelect: WholesomePluginSettings[ 'wholesomecode_wholesome_plugin_example_select' ],
exampleText: WholesomePluginSettings[ '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,
exampleToggle,
isAPILoaded,
} = this.state;
if (! isAPILoaded) {
return (<Placeholder>
<Spinner />
</Placeholder>
);
}
return (<Fragment>
<div className="wholesome-plugin__main">
<Panel>
<PanelBody
title={ __( 'Panel Body One', 'wholesome-plugin') }
icon="admin-plugins"
>
<SelectControl
help={ __( 'An example dropdown field.', 'wholesome-plugin') }
label={ __( 'Example Select', 'wholesome-plugin') }
onChange={ (exampleSelect) => {
this.setState( { exampleSelect } );
customize.value('wholesomecode_wholesome_plugin_example_select')(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 }
/>
</PanelBody>
<PanelBody
title={ __( 'Panel Body Two', '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 } );
customize.value('wholesomecode_wholesome_plugin_example_text')(exampleText);
}}
value={ exampleText }
/>
</PanelBody>
<PanelBody
title={ __( 'Panel Body Three', 'wholesome-plugin') }
icon="admin-plugins"
>
<TextControl
help={ __( 'Use PanelRow to place controls inline.', 'wholesome-plugin') }
label={ __( 'Example Text 2', 'wholesome-plugin') }
onChange={ (exampleText2) => {
this.setState( { exampleText2 } );
customize.value('wholesomecode_wholesome_plugin_example_text_2')(exampleText2);
}}
value={ exampleText2 }
/>
</PanelBody>
<PanelBody
title={ __( 'Panel Body Four', 'wholesome-plugin') }
icon="admin-plugins"
>
<ToggleControl
checked={ exampleToggle }
help={ __( 'An example toggle.', 'wholesome-plugin') }
label={ __( 'Example Toggle', 'wholesome-plugin') }
onChange={ (exampleToggle) => {
this.setState( { exampleToggle } );
customize.value('wholesomecode_wholesome_plugin_example_toggle')(exampleToggle);
}}
/>
</PanelBody>
</Panel>
</div>
</Fragment>) }
}
Uma mudança notável é aquela dentro componentDidMountde, onde as configurações são carregadas da API. Observe que as duas configurações que serão acessadas get_theme_modsão acessadas usando a variável WholesomePluginSettingsque criamos na wp_localize_scriptfunção anteriormente neste guia.
this.setState( {
exampleSelect: WholesomePluginSettings[ 'wholesomecode_wholesome_plugin_example_select' ],
exampleText: WholesomePluginSettings[ '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,
} );
Lidar com o Salvar
Nós realmente não precisamos fazer nada de especial para lidar com as mudanças. A única coisa que precisamos fazer é conectar customizee deixar o WordPress Customizer lidar com o salvamento, por exemplo:
onChange={ (exampleSelect) => {
this.setState( { exampleSelect } );
customize.value('wholesomecode_wholesome_plugin_example_select')(exampleSelect);
}}
Neste exemplo, ele onChangepassa o valor do campo de entrada (neste caso nosso <select>) e atualiza o estado e, em seguida, passa esse valor para o Personalizador por meio da wp.customize.value()função.
Crie a seção e o painel do personalizador com JavaScript
Na parte inferior do /src/customizer.jsarquivo adicione o seguinte código:
customize.bind('ready', function() {
const panelKey = 'wholesomecode-wholesome-plugin-customizer-panel';
const sectionKey = 'wholesomecode-wholesome-plugin-customizer-section';
customize.panel.add(
new customize.Panel( panelKey, {
description: __( 'Wholesome Plugin Example Panel', 'wholesome-plugin' ),
priority: 1000,
title: __( 'Wholesome Plugin Panel', 'wholesome-plugin' ),
})
);
customize.section.add(
new customize.Section( sectionKey, {
customizeAction: __( 'Wholesome Plugin ▸ Section', 'wholesome-plugin' ),
panel: panelKey,
title: __( 'Wholesome Plugin Section', 'wholesome-plugin' ),
})
);
customize.control.add(
new customize.Control( 'wholesomecode-wholesome-plugin-customizer-gutenberg-control', {
section: sectionKey,
type: 'wholesome-plugin-gutenberg-control',
})
);
const htmlOutput = document.getElementById( 'wholesome-plugin-customizer' );
if (htmlOutput) {
render(
<App />,
htmlOutput
);
}
});
Este código cria a seção e o Painel do Customizador em JavaScript.
O código também adiciona nosso controle Gutenberg personalizado registrando uma new customize.Controlclasse e passando o typecom o mesmo nome typeque definimos quando registramos o controle em PHP.
Também usamos este código para encontrar o <div>que registramos em nosso controle personalizado do Gutenberg e renderizar os componentes do Gutenberg nele <div>.
Adicione o SCSS
Precisamos arrumar o painel um pouco adicionando o seguinte SCSS em /src/customizer.scss:
#wholesome-plugin-customizer {
.components-placeholder {
background: #f1f1f1;
}
.wholesome-plugin__main {
margin-left: auto;
margin-right: auto;
.components-panel {
background: none;
border: none;
}
.components-panel__body {
background: #ffffff;
border: 1px solid #e2e4e7;
margin-bottom: 1rem;
}
}
.components-base-control__help {
margin-top: .5rem;
}
.components-panel__row {
> div {
flex-grow: 1;
margin-right: 1rem;
&:last-of-type {
margin-right: 0;
}
}
}
.wholesome-plugin__notices {
.components-snackbar {
bottom: .5rem;
position: fixed;
}
}
}
Visualizando o personalizador
Navegue até o WordPress Customizer e veja o Gutenberg Customizer Panel em ação:
O personalizador com componentes Gutenberg
- Dê uma olhada na criação de blocos filho aninhados com o
InnerBlockscomponente - Dê uma olhada no uso de meta campos post em blocos Gutenberg