← Voltar ao blog

Magento 2 Page Builder: criando um content type customizado

Rodrigo Biazzi

O Page Builder é o editor de arrastar e soltar para páginas CMS, blocks, categorias e descrições de produto. Começou como recurso do Adobe Commerce e está incluído no Magento Open Source desde o 2.4.3, então no 2.4.8 as duas edições o têm. Ele vem com rows, colunas, texto, imagens, banners, sliders e mais algumas coisas. Quando os editores precisam de um componente específico da sua loja, como uma citação estilizada, uma lista de diferenciais ou um teaser do localizador de lojas, você pode adicioná-lo como um content type customizado.

Este artigo percorre um content type pequeno, uma citação com autor, e explica cada arquivo. É a mesma estrutura dos exemplos de Page Builder da própria Adobe, e escala para content types maiores.

Como o Page Builder guarda o conteúdo

Este é o ponto mais importante a entender antes de construir qualquer coisa. O Page Builder não guarda JSON. Ele guarda HTML no campo de conteúdo normal, com atributos data que descrevem cada elemento:

<div data-content-type="vendor_quote" data-appearance="default" data-element="main">
    <blockquote data-element="quote">Good tools make good work.</blockquote>
    <cite data-element="author">Someone</cite>
</div>

Quando um editor abre o conteúdo, o Page Builder lê esse HTML de volta para o seu modelo de dados. Quando salva, escreve HTML de novo. Duas consequências:

  • O storefront renderiza o HTML armazenado diretamente. Um content type simples não precisa de PHP nem de JavaScript no storefront.
  • O HTML que o seu content type escreve é um contrato. Mudar a estrutura depois significa que o conteúdo antigo pode não ser lido de volta corretamente, então desenhe com cuidado desde o início.

Planeje antes de construir

Como o HTML armazenado é difícil de mudar depois, gaste alguns minutos num plano antes de escrever XML. Anote os campos que os editores vão preencher, quais são texto simples e quais precisam de rich text, quais opções de estilo eles realmente precisam e o HTML exato que você quer no storefront. Olhe o design em todos os breakpoints, não só no desktop. Depois confira se um content type existente com uma classe CSS do fieldset advanced já resolve. Muitos pedidos de content type novo acabam sendo um elemento de texto com uma classe, o que não custa nada de manutenção.

Arquivos envolvidos

app/code/Vendor/PageBuilderQuote/
    registration.php
    etc/module.xml
    view/adminhtml/pagebuilder/content_type/vendor_quote.xml
    view/adminhtml/ui_component/pagebuilder_vendor_quote_form.xml
    view/adminhtml/web/template/content-type/vendor-quote/default/preview.html
    view/adminhtml/web/template/content-type/vendor-quote/default/master.html
    view/frontend/web/css/source/_module.less

Adicione Magento_PageBuilder ao sequence no module.xml, para a sua configuração carregar depois dos content types do core.

1. A configuração do content type

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_PageBuilder:etc/content_type.xsd">
    <type name="vendor_quote"
          label="Quote"
          component="Magento_PageBuilder/js/content-type"
          preview_component="Magento_PageBuilder/js/content-type/preview"
          master_component="Magento_PageBuilder/js/content-type/master"
          form="pagebuilder_vendor_quote_form"
          menu_section="elements"
          icon="icon-pagebuilder-heading"
          sortOrder="50"
          translate="label">
        <children default_policy="deny"/>
        <appearances>
            <appearance name="default"
                        default="true"
                        preview_template="Vendor_PageBuilderQuote/content-type/vendor-quote/default/preview"
                        master_template="Vendor_PageBuilderQuote/content-type/vendor-quote/default/master"
                        reader="Magento_PageBuilder/js/master-format/read/configurable">
                <elements>
                    <element name="main">
                        <style name="text_align" source="text_align"/>
                        <style name="margins" storage_key="margins_and_padding" reader="Magento_PageBuilder/js/property/margins" converter="Magento_PageBuilder/js/converter/style/margins"/>
                        <style name="padding" storage_key="margins_and_padding" reader="Magento_PageBuilder/js/property/paddings" converter="Magento_PageBuilder/js/converter/style/paddings"/>
                        <attribute name="name" source="data-content-type"/>
                        <attribute name="appearance" source="data-appearance"/>
                        <css name="css_classes"/>
                    </element>
                    <element name="quote">
                        <html name="quote_text" converter="Magento_PageBuilder/js/converter/html/tag-escaper"/>
                    </element>
                    <element name="author">
                        <html name="quote_author" converter="Magento_PageBuilder/js/converter/html/tag-escaper"/>
                    </element>
                </elements>
            </appearance>
        </appearances>
    </type>
</config>

O que fazem as partes principais:

  • name é o identificador gravado em data-content-type. Escolha uma vez e mantenha, já que o conteúdo armazenado se refere a ele.
  • component, preview_component e master_component apontam para as classes genéricas do core. Você só escreve seu próprio preview component quando o stage precisa de comportamento customizado, como um preview ao vivo que chama uma API.
  • form é o formulário UI component que os editores veem ao editar o elemento.
  • menu_section é o grupo no painel da esquerda. O core usa layout, elements, media e add_content.
  • children com default_policy="deny" impede que os editores soltem outros content types dentro da citação.
  • elements mapeiam campos do formulário para o HTML. O nome de cada element corresponde a um data-element nos templates. style escreve estilos inline, attribute escreve atributos, css escreve classes e html escreve o HTML interno.

O converter tag-escaper escapa tags HTML em campos de texto simples, assim um editor que digita sinais de menor e maior não quebra a marcação. Use um campo WYSIWYG e outro converter só quando você realmente quer rich text dentro do elemento.

O mapeamento de margin e padding acima segue o padrão que os content types do core usam com o fieldset advanced compartilhado. Abra vendor/magento/module-page-builder/view/adminhtml/pagebuilder/content_type/heading.xml e compare. Copiar de um tipo do core com formato parecido é o jeito mais confiável de acertar esses mapeamentos.

2. O formulário de edição

O formulário é um formulário UI component comum do admin que estende o pagebuilder_base_form. O form base traz os fieldsets compartilhados de appearance e advanced, como alinhamento, bordas, margins, padding e classes CSS. O começo seguro mais rápido é copiar um formulário pequeno do core, por exemplo o pagebuilder_heading_form.xml em vendor/magento/module-page-builder/view/adminhtml/ui_component/, renomear o namespace e o data source para casar com o nome do seu arquivo e trocar os campos pelos seus:

<fieldset name="general" sortOrder="20">
    <settings>
        <label/>
    </settings>
    <field name="quote_text" sortOrder="10" formElement="textarea">
        <settings>
            <dataScope>quote_text</dataScope>
            <dataType>text</dataType>
            <label translate="true">Quote</label>
            <validation>
                <rule name="required-entry" xsi:type="boolean">true</rule>
            </validation>
        </settings>
    </field>
    <field name="quote_author" sortOrder="20" formElement="input">
        <settings>
            <dataScope>quote_author</dataScope>
            <dataType>text</dataType>
            <label translate="true">Author</label>
        </settings>
    </field>
</fieldset>

Os valores de dataScope precisam casar com os atributos name dos nós html no XML do content type. Uma divergência é o motivo mais comum de um campo salvar mas nunca aparecer no stage.

Se você é novo em formulários UI component do admin, os fundamentos de UI components explicam o framework por baixo.

3. Templates de preview e master

Cada appearance tem dois templates Knockout. O template preview renderiza no stage do Page Builder no admin, com o menu de opções que deixa os editores mover, editar, duplicar e remover o elemento. O template master produz o HTML que é salvo e exibido no storefront.

preview.html:

<div attr="data.main.attributes"
     ko-style="data.main.style"
     css="data.main.css"
     class="pagebuilder-content-type"
     event="{ mouseover: onMouseOver, mouseout: onMouseOut }, mouseoverBubble: false">
    <render args="getOptions().template"/>
    <blockquote attr="data.quote.attributes" ko-style="data.quote.style" css="data.quote.css" html="data.quote.html"></blockquote>
    <cite attr="data.author.attributes" ko-style="data.author.style" css="data.author.css" html="data.author.html"></cite>
</div>

master.html:

<div attr="data.main.attributes" ko-style="data.main.style" css="data.main.css">
    <blockquote attr="data.quote.attributes" ko-style="data.quote.style" css="data.quote.css" html="data.quote.html"></blockquote>
    <cite attr="data.author.attributes" ko-style="data.author.style" css="data.author.css" html="data.author.html"></cite>
</div>

Mantenha o template master livre de marcação e event handlers só do editor. Tudo o que estiver nele vai parar no conteúdo armazenado e no storefront.

4. Estilo no storefront

Como o storefront só enxerga o HTML armazenado, o estilo é CSS simples mirando nos atributos data:

[data-content-type='vendor_quote'] blockquote {
    font-size: 1.5rem;
    font-style: italic;
    margin: 0 0 0.5rem;
}

[data-content-type='vendor_quote'] cite {
    display: block;
    font-style: normal;
    opacity: 0.8;
}

Coloque os estilos do admin também na área adminhtml, para o stage ficar parecido com o storefront. Os editores confiam no que veem no stage.

Se o content type precisa de comportamento no storefront, como um slider, adicione um widget initialiser para ele na área frontend. Content types do core como o slider fazem isso. Mantenha lazy, porque o script carrega onde quer que o conteúdo apareça.

Deploy e testes

bin/magento setup:upgrade
bin/magento cache:flush
bin/magento setup:static-content:deploy -f --area adminhtml

Depois teste o ciclo completo: adicione o elemento, preencha o formulário, salve, recarregue a página no admin e confira se os valores são lidos de volta, e confira a saída no storefront. Ler de volta depois de salvar é o passo que pega os erros de mapeamento.

Armadilhas

  • Remover o módulo deixa conteúdo para trás. O HTML armazenado continua renderizando no storefront, mas o Page Builder não consegue mais editar esses elementos. Planeje a migração do conteúdo antes de remover um content type.
  • Mudar nomes de elementos quebra o conteúdo antigo. Adicione elementos novos em vez de renomear os existentes.
  • Dado dinâmico não pertence aqui. Um content type armazena HTML estático. Para conteúdo que precisa mudar sem edição, como preços ou estoque, combine com um widget customizado que renderiza no servidor.

Se você está decidindo entre as edições por outros motivos, veja Magento Open Source vs Adobe Commerce. O Page Builder em si não é mais motivo para escolher uma ou outra, embora content staging e previews de mudanças agendadas continuem sendo recursos do Adobe Commerce.

FAQ

O Page Builder está disponível no Magento Open Source?

Sim. Está incluído no Magento Open Source desde o 2.4.3. Content staging, atualizações agendadas e alguns recursos de preview continuam exclusivos do Adobe Commerce.

Preciso de código PHP para um content type customizado?

Não para um simples. O XML de configuração, o formulário e dois templates bastam, porque o storefront renderiza o HTML armazenado diretamente.

Por que meu campo salva mas não aparece no stage?

O dataScope do formulário não casa com o name no XML do content type, ou o nome do element no XML não casa com o data-element nos templates.

Posso adicionar uma nova appearance a um content type do core?

Sim. Declare o mesmo nome de type no seu próprio XML de content_type com um novo nó appearance e templates, e o Magento faz o merge com a configuração do core.

Atendo como freelancer em Magento e Adobe Commerce, incluindo content types de Page Builder para equipes de conteúdo. Se precisar de ajuda com isso, fale comigo.

Artigos relacionados