{"id":228750,"date":"2022-10-16T15:14:00","date_gmt":"2022-10-16T12:14:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=228750"},"modified":"2022-11-09T04:08:35","modified_gmt":"2022-11-09T01:08:35","slug":"usando-opcoes-para-armazenar-dados-no-editor-de-blocos-do-wordpress-gutenberg","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/pt-pt\/usando-opcoes-para-armazenar-dados-no-editor-de-blocos-do-wordpress-gutenberg\/","title":{"rendered":"Usando Op\u00e7\u00f5es para Armazenar Dados no Editor de Blocos do WordPress (Gutenberg)"},"content":{"rendered":"\n<p>Exploramos anteriormente o armazenamento de dados do editor de blocos do WordPress (Gutenberg) em <a href=\"https:\/\/wholesomecode.ltd\/guides\/creating-plugin-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">atributos de bloco<\/a> e em <a href=\"https:\/\/wholesomecode.ltd\/guides\/post-meta-fields-store-attributes-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">post meta<\/a>, mas voc\u00ea sabia que pode armazenar e recuperar na tabela de op\u00e7\u00f5es do WordPress importando <code>api<\/code>de <code>@wordpress\/api<\/code>.<\/p>\n<p>Neste guia, vamos dar uma olhada no que voc\u00ea escreveria classicamente em PHP como <code>update_option<\/code>e <code>get_option<\/code>.<\/p>\n<p>Para implementar isso, precisamos aproveitar o ciclo de vida do React, ent\u00e3o veremos a cria\u00e7\u00e3o de um React Component importando <code>Component<\/code>do <code>@wordpress\/element<\/code>.<\/p>\n<h2>Pr\u00e9-requisitos<\/h2>\n<ul>\n<li>Familiarize-se com a <a href=\"https:\/\/wholesomecode.ltd\/guides\/creating-plugin-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">cria\u00e7\u00e3o de plugins para WordPress Gutenberg<\/a><\/li>\n<li>Familiarize-se <a href=\"https:\/\/wholesomecode.ltd\/guides\/php-render-block-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">com blocos din\u00e2micos e renderiza\u00e7\u00e3o do lado do servidor<\/a><\/li>\n<li>Entenda como voc\u00ea pode <a href=\"https:\/\/wholesomecode.ltd\/guides\/custom-meta-boxes-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">criar meta boxes em Gutenberg<\/a><\/li>\n<\/ul>\n<p>Esse \u00faltimo requisito \u00e9 \u00fatil para a interface do usu\u00e1rio que usaremos neste guia, no entanto, em aplicativos do mundo real, \u00e9 prov\u00e1vel que voc\u00ea use esse m\u00e9todo em uma barra lateral ou p\u00e1gina de op\u00e7\u00f5es.<\/p>\n<h2>Registrar as op\u00e7\u00f5es em PHP<\/h2>\n<p>Antes de podermos usar uma op\u00e7\u00e3o em JavaScript, temos que ter certeza de que a registramos em PHP usando <code>register_setting<\/code>e que o <code>show_in_rest<\/code>argumento foi definido como true.<\/p>\n<p>Seguindo o <a href=\"https:\/\/wholesomecode.ltd\/guides\/php-render-block-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">guia do Bloco Din\u00e2mico<\/a>, abra o arquivo PHP raiz do plug-in (neste caso <code>wholesome-plugin.php<\/code>) e adicione o seguinte c\u00f3digo ao final desse arquivo ap\u00f3s todas as outras fun\u00e7\u00f5es:<\/p>\n<pre><code>function wholesomecode_wholesome_plugin_register_settings() {\n    register_setting(\n        'wholesomecode_wholesome_plugin_settings',\n        'wholesomecode_wholesome_plugin_example_text',\n        [\n            'default'       =&gt; '',\n            'show_in_rest'  =&gt; true,\n            'type'          =&gt; 'string',\n        ]\n    );\n}\nadd_action( 'init', 'wholesomecode_wholesome_plugin_register_settings' );\n<\/code><\/pre>\n<p>Este c\u00f3digo registra um metacampo chamado <code>wholesomecode_wholesome_plugin_block_text<\/code>para o <code>wholesomecode_wholesome_plugin_settings<\/code>grupo de op\u00e7\u00f5es. Tamb\u00e9m garante que a API REST possa acessar esse metacampo com o <code>show_in_rest<\/code>valor definido como true.<\/p>\n<h2>Criar o componente<\/h2>\n<p>Abra o <code>\/src\/edit.js<\/code>arquivo, vamos alterar um pouco a estrutura deste arquivo para que possamos gerar nosso arquivo <code>Component<\/code>.<\/p>\n<p>Recorte e cole a totalidade deste bloco de c\u00f3digo no <code>\/src\/edit.js<\/code>arquivo, abordaremos o que ele faz em um momento:<\/p>\n<pre><code>import { __ } from '@wordpress\/i18n';\nimport { useBlockProps } from '@wordpress\/block-editor';\nimport {\n    Panel,\n    PanelBody,\n    TextControl,\n} from '@wordpress\/components';\nimport { Component } from '@wordpress\/element';\n\nimport '.\/editor.scss';\n\nclass OptionsExample extends Component {\n    constructor() {\n        super( ...arguments );\n        this.state = { exampleText: '' };\n    }\n\n    render() {\n        const { exampleText } = this.state;\n        return (&lt;Panel&gt;\n                &lt;PanelBody\n                    title={ __( 'Example Meta Box', 'wholesome-plugin') }\n                    icon=\"admin-plugins\"\n                &gt;\n                    &lt;TextControl\n                        help={ __( 'This is an example text field.', 'wholesome-plugin') }\n                        label={ __( 'Example Text', 'wholesome-plugin') }\n                        onChange={ (exampleText) =&gt; this.setState( { exampleText }) }\n                        value={ exampleText }\n                    \/&gt;\n                &lt;\/PanelBody&gt;\n            &lt;\/Panel&gt;) }\n}\n\nexport default function Edit( props) {\n    return (&lt;div { ...useBlockProps() }&gt;\n            &lt;OptionsExample { ...props }\/&gt;\n        &lt;\/div&gt;\n    );\n}\n<\/code><\/pre>\n<p>Voc\u00ea pode reconhecer que a interface do usu\u00e1rio que implementamos \u00e9 exatamente a mesma do guia <a href=\"https:\/\/wholesomecode.ltd\/guides\/custom-meta-boxes-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Gutenberg Meta Box<\/a>, onde usamos meta atributos post. Voc\u00ea tamb\u00e9m pode notar que ainda n\u00e3o estamos obtendo ou configurando informa\u00e7\u00f5es usando op\u00e7\u00f5es e, em vez disso, estamos apenas usando o componente <code>state<\/code>.<\/p>\n<h3>Usando Estado<\/h3>\n<p>A raz\u00e3o pela qual criamos um componente personalizado e o passamos para nossa <code>Edit<\/code>fun\u00e7\u00e3o \u00e9 para que possamos aproveitar o estado. Fizemos isso porque:<\/p>\n<ul>\n<li>Vamos criar uma fun\u00e7\u00e3o para carregar as op\u00e7\u00f5es da API, e precisamos armazenar isso no estado para que nossos componentes possam l\u00ea-lo<\/li>\n<li>N\u00e3o queremos que a API atualize as op\u00e7\u00f5es assim que o texto mudar em nossa caixa de texto, ent\u00e3o precisamos de uma fun\u00e7\u00e3o para salvar o estado nas op\u00e7\u00f5es por meio da API depois que a postagem for salva<\/li>\n<\/ul>\n<p>Usar o estado \u00e9 bastante simples. No construtor inicializamos o estado assim:<\/p>\n<pre><code>this.state = { exampleText: '' };\n<\/code><\/pre>\n<p>E no componente acessamos de forma semelhante a como acessamos atributos no guia anterior:<\/p>\n<pre><code>const { exampleText } = this.state;\n<\/code><\/pre>\n<p>A diferen\u00e7a \u00e9 que, em nosso <code>onChange<\/code>m\u00e9todo, em vez de usar <code>setAttributes<\/code>usamos <code>this.setState<\/code>.<\/p>\n<h3>Obtendo op\u00e7\u00f5es da API<\/h3>\n<p>Na parte superior do documento, importe <code>api<\/code>de <code>@wordpress\/api<\/code>:<\/p>\n<pre><code>import api from '@wordpress\/api';\n<\/code><\/pre>\n<p>Adicione uma nova propriedade onde o estado \u00e9 inicializado de <code>isAPILoaded<\/code>. Precisaremos disso para garantir que n\u00e3o tentamos acessar a API ou renderizar o componente antes que a API seja carregada.<\/p>\n<pre><code>this.state = {\n  exampleText: '',\n  isAPILoaded: false,\n};\n<\/code><\/pre>\n<p>Agora dentro do Component que criamos, adicione um bloco de c\u00f3digo sob o construtor chamado <code>componentDidMount<\/code>. Este \u00e9 um m\u00e9todo de ciclo de vida React, que \u00e9 chamado depois que um componente foi adicionado ao DOM.<\/p>\n<p>Nesse bloco de c\u00f3digo, adicione o seguinte:<\/p>\n<pre><code>componentDidMount() {\n  api.loadPromise.then(() =&gt; {\n    this.settings = new api.models.Settings();\n\n    const { isAPILoaded } = this.state;\n\n    if (isAPILoaded === false) {\n      this.settings.fetch().then( (response) =&gt; {\n        this.setState( {\n          exampleText: response[ 'wholesomecode_wholesome_plugin_example_text' ],\n          isAPILoaded: true,\n        } );\n      } );\n    }\n  } );\n}\n<\/code><\/pre>\n<p>Aqui estamos acessando a op\u00e7\u00e3o que registramos anteriormente com a <code>register_setting<\/code>fun\u00e7\u00e3o.<\/p>\n<p>Este bloco de c\u00f3digo faz o seguinte:<\/p>\n<ul>\n<li>Obt\u00e9m as configura\u00e7\u00f5es da API de configura\u00e7\u00f5es do WordPress Guttenberg.<\/li>\n<li>Obt\u00e9m <code>isAPILoaded<\/code>do estado<\/li>\n<li>Se a API n\u00e3o foi carregada, ela busca as configura\u00e7\u00f5es da API em um<code>response<\/code><\/li>\n<li>Em seguida, definimos o estado para atualizar o estado com a op\u00e7\u00e3o que queremos acessar e definimos o <code>isAPILoaded<\/code>estado como verdadeiro<\/li>\n<\/ul>\n<h3>Pare a renderiza\u00e7\u00e3o do bloco sem configura\u00e7\u00f5es<\/h3>\n<p>N\u00e3o queremos que nosso bloco seja renderizado antes que as configura\u00e7\u00f5es sejam preenchidas. Para cuidar disso, podemos importar um PlaceHolder e um Spinner de <code>$wordpress\/components<\/code>:<\/p>\n<pre><code>import {\n    Panel,\n    PanelBody,\n    Placeholder,\n    Spinner,\n    TextControl,\n} from '@wordpress\/components';\n<\/code><\/pre>\n<p>Em seguida, no m\u00e9todo de renderiza\u00e7\u00e3o do componente, certifique-se de obter <code>isAPILoaded<\/code>do estado e de sa\u00edda <code>Placeholder<\/code>e <code>Spinner<\/code>se n\u00e3o tiver:<\/p>\n<pre><code>const {\n  exampleText,\n  isAPILoaded,\n} = this.state;\n\nif (! isAPILoaded) {\n  return (&lt;Placeholder&gt;\n      &lt;Spinner \/&gt;\n    &lt;\/Placeholder&gt;\n  );\n}\n<\/code><\/pre>\n<p>Dessa forma, se as op\u00e7\u00f5es n\u00e3o foram carregadas, obtemos um bom espa\u00e7o reservado at\u00e9 que o componente seja carregado:<\/p>\n<p>Espa\u00e7o reservado e girador<\/p>\n<h3>Conectando-se ao Gutenberg em Salvar<\/h3>\n<p>Agora que estamos lendo as op\u00e7\u00f5es da tabela de op\u00e7\u00f5es, precisamos de uma maneira de salvar essas op\u00e7\u00f5es quando as alteramos. Para fazer isso, vamos ao <code>subscribe<\/code>armazenamento de dados do WordPress Gutenberg, que indicar\u00e1 quando algo mudou.<\/p>\n<p>Usando isso, criaremos um ouvinte para quando a postagem for salva e salvaremos nossas configura\u00e7\u00f5es quando isso acontecer.<\/p>\n<p>Para fazer essa importa\u00e7\u00e3o <code>subscribe<\/code>e <code>select<\/code>de <code>@wordpress\/data<\/code>.<\/p>\n<pre><code>import { select, subscribe } from '@wordpress\/data';\n<\/code><\/pre>\n<p>Em seguida, no topo do <code>componentDidMount<\/code>bloco de c\u00f3digo, escreva o seguinte:<\/p>\n<pre><code>subscribe(() =&gt; {\n  const { exampleText } = this.state;\n\n  const isSavingPost = select('core\/editor').isSavingPost();\n  const isAutosavingPost = select('core\/editor').isAutosavingPost();\n\n  if (isAutosavingPost) {\n    return;\n  }\n\n  if (! isSavingPost) {\n    return;\n  }\n\n  const settings = new api.models.Settings( {\n    [ 'wholesomecode_wholesome_plugin_example_text' ]: exampleText,\n  } );\n  settings.save();\n});\n<\/code><\/pre>\n<p>O c\u00f3digo faz o seguinte:<\/p>\n<ul>\n<li>Verifica se a postagem est\u00e1 salvando<\/li>\n<li>Verifique se o salvamento \u00e9 um salvamento autom\u00e1tico<\/li>\n<li>Se a postagem estiver salvando e n\u00e3o for um salvamento autom\u00e1tico, envie as novas configura\u00e7\u00f5es para a API de configura\u00e7\u00f5es<\/li>\n<li>Acione um salvamento da API de configura\u00e7\u00f5es.<\/li>\n<\/ul>\n<h3>Um pequeno hack<\/h3>\n<p>Poder\u00edamos deixar nosso c\u00f3digo assim, mas como estamos colocando nossas configura\u00e7\u00f5es em um bloco, e n\u00e3o em uma barra lateral ou outro componente do editor, se alterarmos uma das op\u00e7\u00f5es, e nada mais no editor, o bot\u00e3o &#8216;salvar&#8217; n\u00e3o tornar-se ativo.<\/p>\n<p>Isso porque n\u00e3o estamos usando <code>setAttributes<\/code>nem nada para alterar o c\u00f3digo real do bloco.<\/p>\n<p>Podemos contornar isso, apenas editando outra parte do post ou adicionando um pequeno hack no <code>TextControl<\/code>c\u00f3digo:<\/p>\n<pre><code>onChange={ (exampleText) =&gt; { this.setState( { exampleText } ); setAttributes( { exampleText }) } }\n<\/code><\/pre>\n<p>Lembrando de colocar essa linha de c\u00f3digo no topo do m\u00e9todo render para extrair <code>setAttributes<\/code>do <code>props<\/code>(porque estamos usando um Component acessamos props um pouco diferente com <code>this<\/code>.<\/p>\n<pre><code>const { setAttributes } = this.props;\n<\/code><\/pre>\n<p>Agora, quando mudamos nosso atributo, um atributo &#8216;fake&#8217; vai mudar, fazendo com que o editor pense que agora podemos salvar o post.<\/p>\n<p>\u00c9 um pouco hacky, mas para este caso de uso ele faz o que precisamos.<\/p>\n<h3>Todo o <code>Edit<\/code>c\u00f3digo<\/h3>\n<p>Aqui est\u00e1 todo o c\u00f3digo que voc\u00ea precisa para o <code>Edit<\/code>m\u00e9todo:<\/p>\n<p>i `importar {} de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/i18n&#8217;; importar api de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/api&#8217;; import { useBlockProps } de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/block-editor&#8217;; import { Panel, PanelBody, Placeholder, Spinner, TextControl, } from &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/components&#8217;; import { selecione, assine } de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/data&#8217;; import { Componente } de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/element&#8217;;<\/p>\n<p>import &#8216;.\/editor.scss&#8217;;<\/p>\n<p>class OptionsExample extends Component { constructor() { super( \u2026arguments );<\/p>\n<pre><code>    this.state = {\n        exampleText: '',\n        isAPILoaded: false,\n    };\n}\n\ncomponentDidMount() {\n\n    subscribe( () =&gt; {\n        const { exampleText } = this.state;\n\n        const isSavingPost = select('core\/editor').isSavingPost();\n        const isAutosavingPost = select('core\/editor').isAutosavingPost();\n\n        if (isAutosavingPost) {\n            return;\n        }\n\n        if (! isSavingPost) {\n            return;\n        }\n\n        const settings = new api.models.Settings( {\n            [ 'wholesomecode_wholesome_plugin_example_text' ]: exampleText,\n        } );\n        settings.save();\n    });\n\n    api.loadPromise.then( () =&gt; {\n        this.settings = new api.models.Settings();\n\n        const { isAPILoaded } = this.state;\n\n        if (isAPILoaded === false) {\n            this.settings.fetch().then( (response) =&gt; {\n                this.setState( {\n                    exampleText: response[ 'wholesomecode_wholesome_plugin_example_text' ],\n                    isAPILoaded: true,\n                } );\n            } );\n        }\n    } );\n}\n\nrender() {\n    const {\n        exampleText,\n        isAPILoaded,\n    } = this.state;\n\n    const { setAttributes } = this.props;\n\n    if (! isAPILoaded) {\n        return (&lt;Placeholder&gt;\n                &lt;Spinner \/&gt;\n            &lt;\/Placeholder&gt;\n        );\n    }\n\n    return (&lt;Panel&gt;\n            &lt;PanelBody\n                title={ __( 'Example Meta Box', 'wholesomecode') }\n                icon=\"admin-plugins\"\n            &gt;\n                &lt;TextControl\n                    help={ __( 'This is an example text field.', 'wholesome-plugin') }\n                    label={ __( 'Example Text', 'wholesome-plugin') }\n                    onChange={ (exampleText) =&gt; { this.setState( { exampleText } ); setAttributes( { exampleText }) } }\n                    value={ exampleText }\n                \/&gt;\n            &lt;\/PanelBody&gt;\n        &lt;\/Panel&gt;) }\n<\/code><\/pre>\n<p>}<\/p>\n<p>export fun\u00e7\u00e3o padr\u00e3o Edit(props) { return (<\/p>\n<p>); }<\/p>\n<pre><code>\n### Remove the Attributes\n\nOption 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.\n\nRender the Output\n\nBecause we have saved our attribute as settings in the WordPress options table, we could output this anywhere in WordPress using `get_option`:\n<\/code><\/pre>\n<p>get_option( &#8216;wholesomecode_wholesome_plugin_block_text&#8217;, &quot; );<\/p>\n<pre><code>\nContinuing 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.\n\nWith this in mind, let\u2019s update our `register_block_type` to output the option:\n<\/code><\/pre>\n<p>register_block_type( &#8216;wholesomecode\/wholesome-plugin&#8217;, array( &#8216;editor_script&#8217; =&gt; &#8216;wholesomecode-wholesome-plugin-block-editor&#8217;, &#8216;editor_style&#8217; =&gt; &#8216;wholesomecode-wholesome-plugin-block-editor&#8217;, &#8216;render_callback&#8217; = &gt; function( $atributos, $conte\u00fado) { $example_text = get_option(&#8216;wholesomecode_wholesome_plugin_example_text&#8217;); return &quot;<\/p>\n<p>$example_text<\/p>\n<p>&quot;; }, &#8216;style&#8217; =&gt; &#8216;wholesomecode-wholesome-plugin-block&#8217;,) );<\/p>\n<pre><code>\nNote 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.\n\n5.  \nUsing the Block\n--------------------\n\nPutting it all together, let\u2019s see the block in action:\n\n![Using the block editor for settings and options](https:\n\nExtra: Add Some More Fields\n-----------------------------\n\nIn the extra steps of the Custom Meta Box guide, we added in some extra fields. Let\u2019s update the `Edit` method to include those same fields (note that I have omitted the hack):\n<\/code><\/pre>\n<p>importar {} de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/i18n&#8217;; importar api de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/api&#8217;; import { useBlockProps } de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/block-editor&#8217;; import { Panel, PanelBody, PanelRow, Placeholder, SelectControl, Spinner, TextControl, ToggleControl, } from &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/components&#8217;; import { selecione, assine } de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/data&#8217;; import { Componente } de &#8216; <a href=\"https:\/\/hashnode.com\/@wordpress\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">@wordpress<\/a> \/element&#8217;;<\/p>\n<p>import &#8216;.\/editor.scss&#8217;;<\/p>\n<p>class OptionsExample extends Component { constructor() { super( \u2026arguments );<\/p>\n<pre><code>    this.state = {\n        exampleSelect: '',\n        exampleText: '',\n        exampleText2: '',\n        exampleText3: '',\n        exampleToggle: false,\n        isAPILoaded: false,\n    };\n}\n\ncomponentDidMount() {\n\n    subscribe( () =&gt; {\n        const {\n            exampleSelect,\n            exampleText,\n            exampleText2,\n            exampleText3,\n            exampleToggle,\n        } = this.state;\n\n        const isSavingPost = select('core\/editor').isSavingPost();\n        const isAutosavingPost = select('core\/editor').isAutosavingPost();\n\n        if (isAutosavingPost) {\n            return;\n        }\n\n        if (! isSavingPost) {\n            return;\n        }\n\n        const settings = new api.models.Settings( {\n            [ 'wholesomecode_wholesome_plugin_example_select' ]: exampleSelect,\n            [ 'wholesomecode_wholesome_plugin_example_text' ]: exampleText,\n            [ 'wholesomecode_wholesome_plugin_example_text_2' ]: exampleText2,\n            [ 'wholesomecode_wholesome_plugin_example_text_3' ]: exampleText3,\n            [ 'wholesomecode_wholesome_plugin_example_toggle' ]: exampleToggle,\n        } );\n        settings.save();\n    });\n\n    api.loadPromise.then( () =&gt; {\n        this.settings = new api.models.Settings();\n\n        const { isAPILoaded } = this.state;\n\n        if (isAPILoaded === false) {\n            this.settings.fetch().then( (response) =&gt; {\n                this.setState( {\n                    exampleSelect: response[ 'wholesomecode_wholesome_plugin_example_select' ],\n                    exampleText: response[ 'wholesomecode_wholesome_plugin_example_text' ],\n                    exampleText2: response[ 'wholesomecode_wholesome_plugin_example_text_2' ],\n                    exampleText3: response[ 'wholesomecode_wholesome_plugin_example_text_3' ],\n                    exampleToggle: Boolean( response[ 'wholesomecode_wholesome_plugin_example_toggle' ] ),\n                    isAPILoaded: true,\n                } );\n            } );\n        }\n    } );\n}\n\nrender() {\n    const {\n        exampleSelect,\n        exampleText,\n        exampleText2,\n        exampleText3,\n        exampleToggle,\n        isAPILoaded,\n    } = this.state;\n\n    if (! isAPILoaded) {\n        return (&lt;Placeholder&gt;\n                &lt;Spinner \/&gt;\n            &lt;\/Placeholder&gt;\n        );\n    }\n\n    return (&lt;Panel&gt;\n            &lt;PanelBody\n                title={ __( 'Example Meta Box', 'wholesome-plugin') }\n                icon=\"admin-plugins\"\n            &gt;\n                &lt;SelectControl\n                    help={ __( 'An example dropdown field.', 'wholesome-plugin') }\n                    label={ __( 'Example Select', 'wholesome-plugin') }\n                    onChange={ (exampleSelect) =&gt; this.setState( { exampleSelect }) }\n                    options={ [\n                        {\n                            label: __( 'Please Select...', 'wholesome-plugin' ),\n                            value: '',\n                        },\n                        {\n                            label: __( 'Option 1', 'wholesome-plugin' ),\n                            value: 'option-1',\n                        },\n                        {\n                            label: __( 'Option 2', 'wholesome-plugin' ),\n                            value: 'option-2',\n                        },\n                    ] }\n                    value={ exampleSelect }\n                \/&gt;\n                &lt;TextControl\n                    help={ __( 'This is an example text field.', 'wholesome-plugin') }\n                    label={ __( 'Example Text', 'wholesome-plugin') }\n                    onChange={ (exampleText) =&gt; this.setState( { exampleText }) }\n                    value={ exampleText }\n                \/&gt;\n                &lt;PanelRow&gt;\n                    &lt;TextControl\n                        help={ __( 'Use PanelRow to place controls inline.', 'wholesome-plugin') }\n                        label={ __( 'Example Text 2', 'wholesome-plugin') }\n                        onChange={ (exampleText2) =&gt; this.setState( { exampleText2 }) }\n                        value={ exampleText2 }\n                    \/&gt;\n                    &lt;TextControl\n                        help={ __( 'This control is inline.', 'wholesome-plugin') }\n                        label={ __( 'Example Text 3', 'wholesome-plugin') }\n                        onChange={ (exampleText3) =&gt; this.setState( { exampleText3 }) }\n                        value={ exampleText3 }\n                    \/&gt;\n                &lt;\/PanelRow&gt;\n                &lt;ToggleControl\n                    checked={ exampleToggle }\n                    help={ __( 'An example toggle.', 'wholesome-plugin') }\n                    label={ __( 'Example Toggle', 'wholesome-plugin') }\n                    onChange={ (exampleToggle) =&gt; this.setState( { exampleToggle }) }\n                \/&gt;\n            &lt;\/PanelBody&gt;\n        &lt;\/Panel&gt;) }\n<\/code><\/pre>\n<p>}<\/p>\n<p>export fun\u00e7\u00e3o padr\u00e3o Edit(props) { return (<\/p>\n<p>); } `<\/p>\n<p>Aqui est\u00e1 o resultado:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-169009-61e7fab7b579e.png\" alt=\"Usando Op\u00e7\u00f5es para Armazenar Dados no Editor de Blocos do WordPress (Gutenberg)\" \/>Op\u00e7\u00f5es extras<\/p>\n<ul>\n<li>D\u00ea uma olhada na cria\u00e7\u00e3o <a href=\"https:\/\/wholesomecode.ltd\/guides\/template-innerblocks-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">de blocos filho aninhados com o <code>InnerBlocks<\/code>componente<\/a><\/li>\n<li>D\u00ea uma olhada no <a href=\"https:\/\/wholesomecode.ltd\/guides\/post-meta-fields-store-attributes-wordpress-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">uso de meta campos post em blocos Gutenberg<\/a><\/li>\n<li>D\u00ea uma olhada na <a href=\"https:\/\/wholesomecode.ltd\/guides\/create-custom-meta-boxes-using-the-wordpress-block-editor-gutenberg\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">cria\u00e7\u00e3o de Meta Boxes personalizadas em Gutenberg<\/a><\/li>\n<\/ul>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fonte de grava\u00e7\u00e3o:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/wholesomecode.ltd\" class=\"external external_icon\">wholesomecode.ltd<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Exploramos anteriormente o armazenamento de dados do editor de blocos do WordPress (Gutenberg) em atributos de bloco e em meta de postagem, mas voc\u00ea sabia que pode armazenar e recuperar no WordPress &#8230;<\/p>\n","protected":false},"author":1,"featured_media":223685,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[898,722,941,806,846,867],"tags":[1170],"class_list":["post-228750","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-2","category-desenvolvedor","category-gutenberg-8","category-php-8","category-tutoriais","category-wordpress-8","tag-affiai-pt-pt"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/228750","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/comments?post=228750"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/posts\/228750\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media\/223685"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/media?parent=228750"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/categories?post=228750"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/pt-pt\/wp-json\/wp\/v2\/tags?post=228750"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}