Modelos de campos em uma dialog no AEM
Tags: adobeexperiencemanager, aem, beginners, xml
Published: 2022-10-18 12:29:01

Existem várias maneiras de construir dialogs nos componentes do AEM e a variedade de opções melhora a experiência do Author na construção da página. 
Através da necessidade de um acervo de modelos reutilizáveis e simples para as dialogs AEM, decidi criar este artigo com alguns dos principais tipos de campos utilizados e seus respectivos códigos, facilitando a vida do(a) desenvolvedor(a).
Também vou explicar algumas propriedades dos campos e suas utilizações.


### 📌 Textfield

```
<text
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
    fieldDescription="Insira um texto simples, de apenas uma linha"
    fieldLabel="Texto"
    required="{Boolean}true"
    name="./text"/>
```

Aqui temos um exemplo de textfield com algumas propriedades relevantes. O nome editável para que possamos pegar esse input no Java precisa ser repetido tanto na abertura da tag quanto no campo `name=""`.


![Textfield em uma dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qx9mvgns3yj8dpzeynsd.png)

1 - `required="{Boolean}true"`
2 - `fieldLabel="Texto"`
3 - `fieldDescription="Insira um texto simples, de apenas uma linha"`
4 - `sling:resourceType="granite/ui/components/coral/foundation/form/textfield"`

### 📌 Textarea

Tem a mesma propriedade do textfield, mas a área de texto é maior, o que facilidade a visualização do que está sendo digitado.


```
<constraintMessage
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
    fieldDescription="Escreva uma mensagem"
    fieldLabel="Mensagem simples com campo alargado"
    name="./constraintMessage"/>
```


![Textarea example in dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvog3afgm9in55lh0o1o.png)

### 📌 Fileupload

Para que um author possa carregar arquivos na dialog de um componente podemos usar o seguinte modelo:

```
<img
    jcr:primaryType="nt:unstructured"
    sling:resourceType="cq/gui/components/authoring/dialog/fileupload"
    autoStart="{Boolean}true"
    fileNameParameter="./imgName"
    fileReferenceParameter="./img"
    mimeTypes="[image/gif,image/jpeg,image/png,image/webp,image/tiff,image/svg+xml]"
    multiple="{Boolean}false"
    name="./file"
    required="{Boolean}true"
    title="image.title"
    uploadUrl="${suffix.path}"
    allowUpload="{Boolean}false"
    fieldLabel="Imagem"
    useHTML5="{Boolean}true"/>
```


![Exemplo de carregamento de imagem em uma dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wlbx2h64ucvrq6zyzigk.png)

Além de receber um parâmetro de nome na imagem (mas poderia ser no documento, no vídeo, qualquer *asset*), precisamos também receber um `fileReferenceParameter` para identificá-la. 
- `mimeTypes` : limita os tipos de arquivos que podem ser carregados
- `multiple` : limita a quantidade
- `uploadUrl="${suffix.path}"` : captura paths do AEM
- `allowUpload="{Boolean}false"` : é uma recomendação Adobe que os arquivos sejam carregados através do DAM e não diretamente upadas do arquivo do computador. É ideal então é que deixemos esse campo como false, mas pode ser modificado caso necessário


### 📌 Colorfield

Seletor de cores em Hexa ou Rgb/a. O AEM gera cores padrões quando botamos `showDefaultColors="{Boolean}true"` e pode começar com um valor já pré estabelecido configurado em `value="#000000"`.

```
<color
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/colorfield"
    fieldLabel="Selecione uma cor do texto"
    showDefaultColors="{Boolean}true"
    showProperties="{Boolean}true"
    showSwatches="{Boolean}true"
    autogenerateColors="off"
    value="#000000"
    name="./color"/>
```

![Colorfield fechado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1ql55ybnc95xech2zg1.png)

![Colorfield aberto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zvl9fudeibg01uw1xirl.png)

### 📌 Richtext

O richtext dá mais opções de texto, permitindo alterações pré-estabelecidas no código, como negrito, itálico, links, caracteres especiais, quebras de texto, listagens, etc. O código abaixo é um modelo com opções diversas, mas existem outras configurações possíveis ([aqui](https://experienceleague.adobe.com/docs/experience-manager-65/administering/operations/rich-text-editor.html?lang=en) você pode encontrar algumas delas)

```
<text
        jcr:primaryType="nt:unstructured"
        sling:resourceType="cq/gui/components/authoring/dialog/richtext"
        fieldDescription="Insira o texto a ser exibido. Você pode adicionar modificadores de formato."
        fieldLabel="Texto"
        name="./text"
        useFixedInlineToolbar="{Boolean}true">
    <rtePlugins jcr:primaryType="nt:unstructured">
        <edit
                jcr:primaryType="nt:unstructured"
                features="*"/>
        <format
                jcr:primaryType="nt:unstructured"
                features="*"/>
        <subsuperscript
                jcr:primaryType="nt:unstructured"
                features="*"/>
        <lists
                jcr:primaryType="nt:unstructured"
                features="*"/>
        <paraformat
                jcr:primaryType="nt:unstructured"
                features="*">
            <formats jcr:primaryType="cq:WidgetCollection">
                <heading2
                        jcr:primaryType="nt:unstructured"
                        description="Heading 2"
                        tag="h2"/>
                <heading3
                        jcr:primaryType="nt:unstructured"
                        description="Heading 3"
                        tag="h3"/>
                <myparagraph
                        jcr:primaryType="nt:unstructured"
                        description="Paragraph"
                        tag="p"/>
            </formats>
        </paraformat>
        <links
                jcr:primaryType="nt:unstructured"
                features="*"/>
        <misctools
                jcr:primaryType="nt:unstructured"
                features="*"/>
        <fullscreen
                jcr:primaryType="nt:unstructured"
                features="*"/>
        </rtePlugins>
        <uiSettings jcr:primaryType="nt:unstructured">
            <cui jcr:primaryType="nt:unstructured">
                <inline
                    jcr:primaryType="nt:unstructured"
                    toolbar="[format#bold,format#italic,format#underline,subsuperscript#subscript,subsuperscript#superscript,#paraformat,image#imageProps,#justify,#lists,links#modifylink,links#unlink,links#anchor,misctools#specialchars]">
                <popovers jcr:primaryType="nt:unstructured">
                    <lists
                            jcr:primaryType="nt:unstructured"
                            items="[lists#unordered,lists#ordered]"
                            ref="lists"/>
                    <paraformat
                            jcr:primaryType="nt:unstructured"
                            items="paraformat:getFormats:paraformat-pulldown"
                            ref="paraformat"/>
                </popovers>
            </inline>
        </cui>
    </uiSettings>
</text>
```


![Richtext example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rr940sjkjc6vlzmj9j3c.png)

### 📌 NumberField

Este modelo de numberfield atribui um número mínimo e máximo (`max="5"` `min="0"`) e um step, que faz com o que o author possa, além de digitar o número desejado, suba um a um utilizando as setas de controle. O Step pode ser em casas decimais e não necessariamente precisa de um mínimo ou máximo para esse campo, ele pode ser estruturado como for melhor. 

```
<number
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/numberfield"
    fieldLabel="Avaliação"
    fieldDescription="A partir de 1 as estrelas de avaliação aparecem no componente. 0 ou nulo fazem com que a avaliação não apareça."
    max="5"
    min="0"
    name="./number"
    step="1"
    required="{Boolean}false"/>
```


![Numberfield example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i6nq8is948lp0qagk3dx.png)


### 📌 Multifield

Às vezes precisamos de múltiplos campos para que o author escolha a quantidade de componentes a serem inseridos. Isso pode acontecer com imagens em um carrossel, com cards de artigos ou até com listas de links.
É importante ressaltar que, quando temos um multifield, ele precisa ser primeiro chamado enquanto lista na classe Java principal com uma anotação `@ChildResource` e, depois, precisa de uma classe própria para que cada elemento tenha suas próprias propriedades. Esses detalhes não serão abordados neste artigo.

```
<cards
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/form/multifield"
        fieldDescription="Clique em '+' para adicionar um novo card"
        fieldLabel="Cards"
        composite="{Boolean}true">
        <granite:data
                jcr:primaryType="nt:unstructured"
                min-item="1"
                max-item="10"/>
        <field
                granite:class="cmp-teaser__editor-action"
                jcr:primaryType="nt:unstructured"
                sling:resourceType="granite/ui/components/coral/foundation/container"
                name="./cards">
            <items jcr:primaryType="nt:unstructured">
                <accordion
                        granite:class="js-cq-IPEPlugin-container"
                        jcr:primaryType="nt:unstructured"
                        sling:resourceType="granite/ui/components/coral/foundation/accordion"
                        variant="quiet">
                        <granite:data
                                jcr:primaryType="nt:unstructured"
                                accordion-title="./cardTitle"/>
                        <items jcr:primaryType="nt:unstructured">
                                <cardList
                                        jcr:primaryType="nt:unstructured"
                                        jcr:title="Card"
                                        sling:resourceType="granite/ui/components/coral/foundation/container"
                                        maximized="{Boolean}true">
                                        <items jcr:primaryType="nt:unstructured">
                                                <cardTitle
                                                        jcr:primaryType="nt:unstructured"
                                                        sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                        fieldLabel="Título do card"
                                                        emptyText="Título"
                                                        name="./cardTitle"
                                                        required="{Boolean}true"/>
                                                <cardValue
                                                        jcr:primaryType="nt:unstructured"
                                                        sling:resourceType="granite/ui/components/coral/foundation/form/numberfield"
                                                        fieldLabel="Preço"
                                                        required="{Boolean}true"
                                                        step="1"
                                                        name="./cardValue"/>
                                        </items>
                                </cardList>
                        </items>
                </accordion>
            </items>
        </field>
</cards>
```


![Multifield fechado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xou6h04zea2sbcejzlqq.png)


![Multifield aberto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eaw83vl9yvpym0o3hm79.png)


![Propriedades de cada campo multifield](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l33bwkm11zqvujjg97tf.png)

- `<accordion/>` : a tag accordion se refere aos elementos de dentro dessa lista. Nesse caso, temos um cardList que é abraçado pelo cards. O accordion é a retração das informações de cada um desses elementos.
--> Logo abaixo do accordion temos uma tag <granite> que configura os nomes de cada menu retrátil com o cardTitle.
- O cardList é um tipo de container que vai receber as informações de cada elemento, que nesse caso só tem título (textfield) e preço (numberfield), mas poderia ter quantos elementos fossem possíveis.


### 📌 Select

Podemos utilizar quantas opções forem necessárias em um selector e utilizando o seu `value` como parâmetro.

```
<selector
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/form/select"
        fieldLabel="Seletor de opções"
        name="./selector">
        <items jcr:primaryType="nt:unstructured">
                <red
                        jcr:primaryType="nt:unstructured"
                        text="Vermelho"
                        value="red"/>
                <yellow
                        jcr:primaryType="nt:unstructured"
                        text="Amarelo"
                        value="yellow"/>
        </items>
</selector>
```


![Select example in dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l9b1io16k1ak6nx3jlt7.png)


### 📌 Checkbox

Um checkbox pode ser usado para devolver um parâmetro booleano. O campo `checked=""` serve para delimitar se o campo por padrão deve vir marcado ou desmarcado.

```
<checkbox
  jcr:primaryType="nt:unstructured"
  sling:resourceType="granite/ui/components/coral/foundation/form/checkbox"
  fieldDescription="Selecione caso seja verdadeiro"
  name="./checkbox"
  text="Adicionar layout escuro"
  uncheckedValue="false"
  checked="true"
  value="true"/>
```

![Checkbox example in dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o6yxny2d8hr9e35j0hr2.png)

### 📌 Radiogroup

Funciona como um seletor de opções, tal qual o selector.

```
<size
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/radiogroup"
    fieldLabel="Selecione um tamanho de card"
    name="./size"
    vertical="{Boolean}true">
        <items jcr:primaryType="nt:unstructured">
            <small
                    jcr:primaryType="nt:unstructured"
                    checked="{Boolean}true"
                    text="Pequeno"
                    value="small"/>
            <medium
                    jcr:primaryType="nt:unstructured"
                    text="Médio"
                    value="medium"/>
            <large
                    jcr:primaryType="nt:unstructured"
                    text="Grande"
                    value="large"/>
        </items>
</size>
```

![Radiogroup example in dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xi529eodhxfxsrxa21q1.png)

### 📌 Datepicker

O datepicker é útil como seletor de datas e pode incluir também horas e minutos. O formato é adaptável através da propriedade `displayedFormat=""`

```
<date
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/datepicker"
    displayedFormat="DD-MM-YYYY HH:mm"
    fieldLabel="Selecione uma data"
    name="./date"
    type="datetime"
    typeHint="Date"/>
```


![Datepicker example in dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1kpome18dntdir05f55v.png)

### 📌 Pathbrowser & Pathfield

O Pathbrowser serve tanto para redirecionamentos internos quanto externos (como urls). Entretanto, a Adobe sugere que sempre busquemos imagens no próprio banco de dados do AEM (no DAM).
Neste caso o exemplo busca uma imagem, por isso o `rootPath=""` é indicando para o `/content/dam`. Este rootPath pode ser modificado conforme a necessidade.

```
<pathBrowser
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/pathbrowser"
    fieldLabel="Selecione uma imagem"
    name="./pathBrowser"
    required="{Boolean}true"
    rootPath="/content/dam"/>
```

```
<pathField
    jcr:primaryType="nt:unstructured"
    sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
    fieldLabel="Url or path"
    name="./pathField"
    required="{Boolean}false"
    rootPath="/content/dam"/>
```


![Pathbrowser example in dialog](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2zvtc35plt1ffxrbmanr.png)

### Referências

- [Granite UI Foundation Server-side](https://developer.adobe.com/experience-manager/reference-materials/6-5/granite-ui/api/jcr_root/libs/granite/ui/components/coral/foundation/server.html)
- [Configure the Rich Text Editor - Experience League](https://experienceleague.adobe.com/docs/experience-manager-65/administering/operations/rich-text-editor.html?lang=en)
- [Adobe Experience Manager (AEM) - Coral 3 – Granite UI components - Salomão Santos](https://gist.github.com/salomao-santos/0cd0240b9824b52a5fdf777ab712cfe2)