Como criar um widget personalizável no Magento 2
Tags: php, tutorial, braziliandevs, magento2
Published: 2022-07-14 14:36:07

## Contextualizando

### O que é um widget?

*Widgets* são utilizados para adicionar conteúdos dinâmicos ou estáticos às páginas da loja ou blocos de conteúdo do CMS. Os *widgets* são componentes reutilizáveis que podem ser adicionados em qualquer bloco ou página CMS do Magento 2.  Por padrão os seguintes widgets já ficam disponiveis:

- Link da página do CMS;
- Bloco estático CMS;
- Link da Categoria do Catálogo;
- Lista de Novos Produtos do Catálogo;
- Link do produto do catálogo;
- Lista de produtos do catálogo;
- Pedidos e Devoluções;
- Produtos recentemente comparados;
- Produtos vistos recentemente.

---

## Código para criação do widget

É necessário adicionar ao módulo a dependência ao módulo `Magento_Widget` no arquivo `\{Vendor}\{Module}\etc\module.xml`.

```xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="{Vendor}_{Module}">
        <sequence>
            ...
            <module name="Magento_Widget" />
        </sequence>
    </module>
</config>
```

### widget.xml

Este arquivo deve estar localizado na pasta `\{Vendor}\{Module}\etc\widget.xml` e declara a criação do modelo do *widget* para ser registrado nas opções no painel do administrador.

O nó `<widget>` declara um novo *widget* e deve ser filho do nó `<widgets>`, e pode ter um ou mais nós `<parameter>`, que representam campos com os valores necessários para a utilização no *widget*.

```xml
<?xml version="1.0"?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
    <widget class="{Vendor}\{Module}\Block\Widget\{WidgetClassName}" id="{widget_name}">
        <label>{Widget Label}</label>
        <description>{Widget Desrcription}</description>
        <parameters>
            <parameter name="{parameter_name}" xsi:type="text" required="{true/false}" visible="{true/false}" sort_order="{integer}">
                <label>{Parameter Label}</label>
            </parameter>

            <parameter name="{parameter_name}" xsi:type="select" required="{true/false}" visible="{true/false}" sort_order="{integer}">
                <label>{Parameter Label}</label>
                <options>
                    <option name="{option_name}" value="{option_value}">
                        <label>{Option Label}</label>
                    </option>
                </options>
            </parameter>

            <parameter name="{parameter_name}" xsi:type="multiselect" required="{true/false}" visible="{true/false}" sort_order="{integer}">
                <label>{Parameter Label}</label>
                <options>
                    <option name="{option_name}" value="{option_value}">
                        <label>{Option Label}</label>
                    </option>
                </options>
            </parameter>

            <parameter name="{parameter_name}" xsi:type="multiselect" source_model="{Vendor}\{Module}\Model\{Directory}\{ClassName}" required="{true/false}" visible="{true/false}" sort_order="{integer}">
                <label>{Parameter Label}</label>
            </parameter>

            <parameter name="{parameter_name}" xsi:type="block" required="{true/false}" visible="{true/false}" sort_order="{integer}">
                <label>{Parameter Label}</label>
                <block class="{Vendor}\{Module}\Block\{Directory}\Widget\{ClassName}">
                    <data>
                        <item name="button" xsi:type="array">
                            <item name="open" xsi:type="string">Select Product...</item>
                        </item>
                    </data>
                </block>
                <depends>
                    <parameter name="display_mode" value="fixed" />
                </depends>
            </parameter>
        </parameters>

        <containers>
            ...
        </containers>
    </widget>
</widgets>
```

| Nós | Descrição | Tipo |
| --- | --- | --- |
| label | Legenda para identificar o nome do widget (Obrigatório). | String |
| description | Contém uma explicação concisa da finalidade do widget (Obrigatório). | String |
| parameters | Lista de opções do widget. | Object |
| containers | Lista de contêineres de layout, onde o widget pode ser injetado. | Object |

### Bloco do Widget

Um arquivo *Block* deve conter toda a lógica de visualização necessária, é altamente recomendável não ter conter nenhum tipo de HTML ou CSS. Cada Bloco do widget deve extender a partir da classe `\Magento\Framework\View\Element\Template` e implementar a interface `\Magento\Widget\Block\BlockInterface`.

Nesta classe é obrigatório a definição da variável `$_template` para indicar qual o *template* que será renderizado pelo *frontend*.

```php
<?php

namespace {Vendor}\{Module}\Block\Widget;

use Magento\Framework\View\Element\Template;
use Magento\Widget\Block\BlockInterface;

class {WidgetClassName} extends Template implements BlockInterface
{
    protected $_template = "widget/{file_name}.phtml";

    public function {methodName}() {
        // Widget code here
    }
}
```

Para saber mais sobre Blocos e como funciona a exibição deles basta acessar o *post* "[Como criar um bloco no Magento 2](https://dev.to/santanaluc94/como-criar-um-bloco-no-magento-2-25fh)".

### Template

Arquivos de *template* devem seguir a estrutura de pastas `\{Vendor}\{Module}\view\{area}\templates\{paths}\{file_name}.phtml`. No arquivo de *template* podemos usar a variável `$block` para acessar os métodos públicos que a classe *Block* disponibiliza.

Os arquivos de template com a extensão phtml são destinados a conteúdos dinâmicos, mesclando PHP (vindo da classe *Block*) com HTML (descrito no próprio *template*).

Para acessar o valor de algum parâmetro específico basta passar o nome do parâmetro dentro do método `getData()` através da variável `$block`.

```php
<?php
/**
 * @var \{Vendor}\{Module}\Block\Widget\{WidgetClassName} $block 
**/

$block->{methodName}();

$parameterValue = $block->getData('{parameter_name}');
?>
```

---

## Finalizando

> Valores entre chaves (`{test}`) devem ser alterados na implementação do código.

### Habilitando as alterações

Execute o comando PHP para limpar todos os caches de armazenamento em cache do processos.

```bash
php bin/magento cache:clean
php bin/magento flush
```

### Diretórios e Arquivos

Segue a a lista de diretórios e arquivos que devem ser criados.