Files

427 lines
19 KiB
Markdown
Raw Permalink Normal View History

2026-05-06 13:35:47 -03:00
---
title: Construção de Widgets e Layouts
source: https://tdn.totvs.com/pages/viewpage.action?pageId=113803693
path: \Plataforma Documentação técnica\Recurso de Páginas e Widgets (WCM)\Construção de Widgets e Layouts.md
---
# Índice
- 1 [Objetivo](#ConstruçãodeWidgetseLayouts-Objetivo)
- 2 [Vídeos How To](#ConstruçãodeWidgetseLayouts-VídeosHowTo)
- 3 [Construção de componentes WCM no Eclipse](#ConstruçãodeWidgetseLayouts-ConstruçãodecomponentesWCMnoEclipse)
- 3.1 [Criação do Widget](#ConstruçãodeWidgetseLayouts-CriaçãodoWidget)
- 3.2 [Estrutura dos diretórios de widgets](#ConstruçãodeWidgetseLayouts-Estruturadosdiretóriosdewidgetstabelaestruturawidget)
- 3.3 [Exemplo de código JavaScript](#ConstruçãodeWidgetseLayouts-ExemplodecódigoJavaScript)
- 3.4 [Exemplo de código HTML com FreeMarker (view.ftl)](#ConstruçãodeWidgetseLayouts-ExemplodecódigoHTMLcomFreeMarker(view.ftl))
- 3.5 [Criação de Layout](#ConstruçãodeWidgetseLayouts-CriaçãodeLayout)
- 3.6 [Exemplo de código FreeMarker (layout.ftl)](#ConstruçãodeWidgetseLayouts-ExemplodecódigoFreeMarker(layout.ftl))
- 3.7 [Exemplo de código JavaScript](#ConstruçãodeWidgetseLayouts-ExemplodecódigoJavaScript.1)
- 3.8 [Exemplo de códigos para inclusão de componentes nos layouts (view.ftl)](#ConstruçãodeWidgetseLayouts-Exemplodecódigosparainclusãodecomponentesnoslayouts(view.ftl))
- 4 [Snippets](#ConstruçãodeWidgetseLayouts-Snippets)
- 5 [Autocompletar para FreeMarker e JavaScript](#ConstruçãodeWidgetseLayouts-AutocompletarparaFreeMarkereJavaScript)
- 6 [Exportar componente para o servidor Fluig](#ConstruçãodeWidgetseLayouts-ExportarcomponenteparaoservidorFluig)
# Objetivo
O objetivo deste guia é possibilitar ao desenvolvedor criar componentes WCM via Eclipse ou Fluig Studio.
# Vídeos How To
Assista!
Confira os vídeos How To sobre [Criação de páginas com layouts e widgets](https://tdn.totvs.com/pages/viewpage.action?pageId=270925442).
Compatibilidade no modo escuro
Este recurso ainda não é compatível com o modo escuro lançado na atualização [Voyager 2.0](https://tdn.totvs.com/x/6HxjN). Para mais detalhes, consulte a documentação em: add link
# Construção de componentes WCM no Eclipse
Para iniciar o desenvolvimento de um componente WCM no Eclipse ou [Fluig Studio](../Instalação e Atualização/Guia de instalação Fluig Studio.md), é necessário acessar a perspectiva Fluig e criar um novo projeto.
- Acionar o menu ***Window*** na barra de menu.
- Selecionar ***Perspective*** → ***Open Perspective*** → ***Other*...**.
- Selecionar **Fluig** e acionar **OK**.
![](..\..\images\open_fluig_perspective.gif)
**Perspectiva Fluig no Eclipse**
- Clicar com o botão direito do *mouse* no espaço *Package Explorer*.
- Selecionar ***New*** → **Projeto Fluig**.
- Informar o nome do projeto no campo *Project name*.
- Acionar ***Finish***.
![](..\..\images\create_new_project.gif)
**Criação de um novo projeto Fluig**
### Criação do Widget
Com o ambiente de desenvolvimento preparado, pode ser iniciada a criação do *widget* no projeto conforme os passos a seguir.
- Clicar com o botão direito do *mouse* sobre o projeto Fluig criado.
- Selecionar ***New*** → ***Widget***.
![](..\..\images\new_widget_1.png)
- Informar o código do *widget* no campo **Código**. Este campo é uma **chave única** e obrigatório.
O campo Código aceita apenas letras, números e sublinhado.
- Informar o nome do *widget* no campo **Nome**.
- Informar uma breve descrição do *widget* no campo **Descrição**.
- Escolher um dos *templates* disponíveis para o desenvolvimento do *widget* no campo **Template** ou manter o padrão "Nenhum" para não utilizar um modelo de desenvolvimento.
- Acionar ***Next*** para avançar.
![](..\..\images\new_widget_2.png)
- Informar o código, nome e URL para identificação do desenvolvedor do componente (Opcional).
- Informar a categoria do *widget* (Opcional).
As categorias funcionam como filtros para localizar *widgets* mais rapidamente e são listadas no painel esquerdo da janela de seleção de *widgets* exibido ao incluir novos *widgets* em um *slot*.
- Apenas um renderizador é disponibilizado atualmente (FreeMarker).
- Acionar ***Finish*** para concluir a criação do *widget*.
![](..\..\images\new_widget_3.png)
- Concluída a etapa de criação do *widget*, uma estrutura de diretórios será gerada abaixo da pasta "wcm/widget" do projeto.
A descrição dos arquivos gerados está disponível no item [Estrutura dos diretórios de *widgets*](https://tdn.totvs.com/pages/viewpage.action?pageId=113803693).
![](..\..\images\new_widget_4.png)
### Estrutura dos diretórios de *widgets*
| Arquivo/Pasta | Descrição |
| --- | --- |
| [código\_do\_widget] | Nome/Identificador do *widget*. |
| src/main/java | Localização das classes Java, caso exista alguma regra de negócio específica do *widget*. |
| src/main/resources/application.info | Arquivo de configuração do *widget* onde são gravados o código, título e desenvolvedor do *widget*, entre outros dados. Este arquivo será detalhado nas próximas páginas deste documento. |
| src/main/resources/view.ftl | Arquivo de *template* do FreeMarker que será interpretado durante a renderização do *widget*. |
| src/main/resources/edit.ftl | Arquivo que será interpretado durante a renderização do *widget* em modo de edição. Usado para configurar opções específicas para renderização do *widget*, como por exemplo, filtros de data, cotação do dólar, etc. Este arquivo é opcional. Caso não exista, será considerado que o *widget* não possui modo de edição, somente visualização. |
| src/main/resources/[código\_do\_widget].properties | Arquivo de *strings* traduzíveis utilizadas pelo *widget*. Deve possuir derivações de acordo com o idioma suportado pelo *widget*. O padrão será sempre o código do *widget* seguido do sufixo referente à sua linguagem. Por exemplo: um arquivo de tradução para o idioma inglês ficaria “código-do-widget\_EN\_US.properties”. |
| src/main/webapp/icon.png | Ícone utilizado para representar o *widget* no menu lateral da aplicação, ou em qualquer tela que necessite de uma representação visual do componente. Deve possuir a dimensão 55 x 30 *pixels*. |
| src/main/webapp/WEB-INF/web.xml | Descritor padrão de uma aplicação Java para *web*. |
| src/main/webapp/WEB-INF/jboss-web.xml | Descritor específico para o servidor de aplicação. Deve conter obrigatoriamente a propriedade “context-root”. O context-root representa o contexto *web* do *widget* e o recomendado é que o valor seja o próprio código do *widget*. |
| src/main/webapp/resources/css/[código\_do\_widget].css | Folha de estilo do *widget*. |
| src/main/webapp/resources/js/[código\_do\_widget].js | Arquivo JavaScript do *widget* (caso seja necessário). |
| src/main/webapp/resources/images | Pasta específica de imagens do *widget*, caso necessário. |
| src/test/java | Pasta específica para a construção de testes unitários. |
Atenção!
**01.** Não devem ser criadas novas pastas no diretório *"*src/main/resources*"*. O recomendado é que sejam utilizadas as pastas já existentes no projeto.
**02.** Ao criar um *widget*, os itens abaixo devem possuir o mesmo nome. Este nome deve ser **único**, ou seja, não pode ser utilizado em nenhum outro *widget*, pois a duplicidade pode causar problemas durante o *deploy* dos componentes:
- Nome do *widget*.
- Propriedade "context-root" do arquivo jboss-web.xml.
- Propriedade "application.code" do arquivo application.info.
### Exemplo de código JavaScript
```
var HelloWorld = SuperWidget.extend({
message: null,
init: function () {
//code
},
bindings: {
local: {
'show-message': ['click_showMessage']
}
},
showMessage: function () {
$div = $('#helloMessage_' + this.instanceId);
$message = $('<div>').addClass('message').append(this.message);
$div.append($message);
}
});
 
```
### Exemplo de código HTML com FreeMarker (view.ftl)
```
<div id="HelloWorld_${instanceId}" class="super-widget wcm-widget-class fluig-style-guide"
data-params="HelloWorld.instance({message: 'Hello world'})">
<!-- efetua a tradução do texto do objeto i18n -->
<h1>${i18n.getTranslation('hello.example.hello')}</h1>
<div>
<button type="button" class="btn btn-default" data-show-message>${i18n.getTranslation('hello.button.showMessage')}</button>
</div>
<div id='helloMessage_${instanceId}'>
</div>
</div>
```
### Criação de Layout
Com o ambiente de desenvolvimento preparado, pode ser iniciada a criação do *layout* no projeto conforme os passos a seguir.
- Clicar com o botão direito do *mouse* sobre o projeto Fluig criado.
- Selecionar ***New*** → ***Layout***.
![](..\..\images\new_layout_1.png)
- Informar o código do *layout* no campo **Código**. Este campo é uma chave única e obrigatório.
O campo Código aceita apenas letras, números e sublinhado.
- Informar o nome do *layout* no campo **Nome**.
- Informar uma breve descrição do *layout* no campo **Descrição**.
- Escolher um dos *templates* disponíveis para o desenvolvimento do *layout* no campo **Template** ou manter o padrão "Nenhum" para não utilizar um modelo de desenvolvimento.
- Acionar ***Next*** para avançar.
![](..\..\images\new_layout_2.png)
- Informar o código, nome e URL para identificação do desenvolvedor do componente (Opcional).
- Informar a categoria do *layout* (Opcional).
- Apenas um renderizador é disponibilizado atualmente (FreeMarker).
- Acionar ***Finish*** para concluir a criação do *layout*.
![](..\..\images\new_layout_3.png)
- Concluída a etapa de criação do *layout*, uma estrutura de diretórios será gerada abaixo da pasta "wcm/layout" do projeto.
Observação
A estrutura de pastas e arquivos de um componente *Layout* é praticamente a mesma de um componente *Widget*. A principal diferença encontra-se no caminho src/main/resources/ onde os arquivos view.ftl e edit.ftl são substituídos pelo arquivo layout.ftl.
![](..\..\images\new_layout_4.png)
### Exemplo de código FreeMarker (layout.ftl)
```
<div class="fluig-style-guide">
<div id="wcm_header" class="wcm-header-background wcm-header">
<!-- Group left -->
<div class="header-grouper-left">
<a href="home" class="wcm_logo" title="${i18n.getTranslation('layout.label.pagetitle')}">
<#if '${imageLogo}'=='true'>
<img src="${serverContextURL}/resources/images/${pageRender.user.tenantId}/logo_image.png"></img>
<#else>
<img src="${serverContextURL}/resources/images/logo.png"></img>
</#if>
</a>
</div>
<!-- Group right -->
<div class="header-grouper-right">
<!-- Container login -->
<div id="SlotLogin" slot="true" class="slot-header-actions">
<#list (pageRender.getInstancesIds("SlotLogin"))! as id>
${pageRender.renderInstanceNoDecorator(id)}
</#list>
</div>
</div>
</div>
<!-- WCM Wrapper content -->
<div class="wcm-wrapper-content">
<!-- Menu esquerdo -->
<nav class="wcm-navigation wcm-menu-background">
<div id="SlotMenu" slot="true">
<#list (pageRender.getInstancesIds("SlotMenu"))! as id>
${pageRender.renderInstanceNoDecorator(id)}
</#list>
</div>
</nav>
<!-- Wrapper -->
<div class="wcm-all-content">
<div id="wcm-content" class="clearfix wcm-background">
<!--WIDGETS DO LAYOUT -->
<link type="text/css" rel="stylesheet" href="${contextPath}/resources/css/wcm_layout.css"/>
<!-- Onde deverá estar a barra de formatação -->
<#if pageRender.isEditMode()=true>
<div name="formatBar" id="formatBar"></div>
<!-- Div geral -->
<!-- Há CSS distinto para Edição/Visualização -->
<div id="edicaoPagina" class="clearfix">
<#else>
<div id="visualizacaoPagina" class="clearfix">
</#if>
<!-- Titulo da página -->
<div class="slotfull layout-1-1">
<span class="titleArea">${i18n.getTranslation('wcm.layoutdefault.title')}</span>
<h2 class="pageTitle">${pageTitle}</h2>
</div>
<!-- Slot 1 -->
<div class="editable-slot slotfull layout-1-1" id="slotFull1">
<div id="SlotC" slot="true" class="slotint" decorator="false" editableSlot="true">
<#list (pageRender.getInstancesIds("SlotC"))! as id>
${pageRender.renderInstanceNoDecorator(id)}
</#list>
</div>
</div>
<!-- Slot 2 -->
<div class="editable-slot slotfull layout-1-1" id="slotFull2">
<div id="SlotB" slot="true" class="slotint" decorator="false" editableSlot="true">
<#list (pageRender.getInstancesIds("SlotB"))! as id>
${pageRender.renderInstanceNoDecorator(id)}
</#list>
</div>
</div>
<!-- Slot 3 -->
<div class="editable-slot slotfull layout-1-1" id="slotFull3">
<!-- Widget -->
<div id="SlotA" slot="true" class="slotint" decorator="true" editableSlot="true">
<#list (pageRender.getInstancesIds("SlotA"))! as id>
${pageRender.renderInstance(id)}
</#list>
</div>
</div>
</div>
<!-- FIM DAS WIDGETS DO LAYOUT -->
<div id="wcm_footer" class="wcm_footer"></div>
</div>
</div>
</div>
</div>
```
Dica
Para compreender melhor os elementos de um código de layout, leia a [sessão de layouts](http://tdn.totvs.com/display/fluig/Layouts).
### Exemplo de código JavaScript
```
var HelloWorld = SuperWidget.extend({
message: null,
init: function () {
//code
},
bindings: {
local: {
'show-message': ['click_showMessage']
}
},
showMessage: function () {
$div = $('#helloMessage_' + this.instanceId);
$message = $('<div>').addClass('message').append(this.message);
$div.append($message);
}
});
```
### Exemplo de códigos para inclusão de componentes nos layouts (view.ftl)
Os *layouts* customizados do Fluig Plataforma permitem que o desenvolvedor reutilize alguns componentes padrão da plataforma, como o cabeçalho contendo as informações do usuário, campo de busca e notificações globais, rodapé, menu e outros componentes.
Quando o desenvolvedor inicia a criação de um *layout* pelo Eclipse ou Fluig Studio, é possível utilizar alguns exemplos de *layouts* existentes. Em alguns destes *layouts* pré definidos é necessário verificar quais componentes estão presentes e quais foram inseridos, pois algumas vezes é necessário configurar o *slots* no arquivo "src/main/resources/application.info".
Abaixo estão disponíveis alguns exemplos de trechos de código para montagem de componentes no *layout*. Cada um destes códigos possui particularidades e não podem apenas ser incluídos no arquivo view.ftl, pois precisam estar dentro de tags <div> para funcionar de forma correta.
**Inclusão do componente de busca**
- O trecho abaixo deve ser inserido dentro da *tag* <div class="header-grouper-right">, que por sua vez deverá estar dentro da *tag* <div id="wcm\_header" class="wcm-header-background wcm-header">.
- No arquivo src/main/resources/application.info o desenvolvedor deverá incluir: slot.SlotInstantSearch=suggestsearch.
**Componente de Busca**
```
<div id="SlotInstantSearch" slot="true" class="slotint slot-header-actions">
<#list (pageRender.getInstancesIds("SlotInstantSearch"))! as id>
${pageRender.renderInstanceNoDecorator(id)}
</#list>
</div>
```
**Inclusão do componente de notificação/alerta global**
- O trecho abaixo deve ser inserido dentro da *tag* <div class="header-grouper-right">, que por sua vez deverá estar dentro da **tag** <div id="wcm\_header" class="wcm-header-background wcm-header">.
- No arquivo src/main/resources/application.info o desenvolvedor deverá incluir: slot.SlotGlobalAlert=alertpopover.
**Componente de Notificação**
```
<div id="SlotGlobalAlert" slot="true" class="slotint slot-header-actions">
<#list (pageRender.getInstancesIds("SlotGlobalAlert"))! as id>
${pageRender.renderInstanceNoDecorator(id)}
</#list>
</div>
```
# Snippets
A opção Snippets fornece ao desenvolvedor um pequeno trecho de código-exemplo relacionado a um determinado recurso. O objetivo é fornecer um modo rápido e simples para que o desenvolvedor visualize um exemplo de código e dê início à construção do componente.
- Acionar o menu ***Window*** na barra de menu.
- Selecionar ***Show View*** → ***Other*...**
- Expandir a pasta ***General***, selecionar ***Snippets*** e acionar **OK**.
![](..\..\images\show_view_snippets.gif)
A visão Snippets apresentará as opções para Componentes WCM conforme o tipo de arquivo em foco (JavaScript ou FTL):
![](..\..\images\snippets_javascript.png)
![](..\..\images\snippets_ftl.png)
# Autocompletar para FreeMarker e JavaScript
Os arquivos Freemarker (extensão ".ftl"), quando abertos com o editor Freemarker do Fluig Plataforma, dispõe do recurso autocompletar para as diretivas básicas do FTL (iniciadas em "<#") e para as variáveis de contexto nas interpolações do Freemarker ("${}"). Os nomes contextuais disponíveis para o autocompletar são widgetRender e pageRender.
Os arquivos JavaScript (extensão ".js"), quando abertos em um Projeto Fluig, também dispõe do recurso autocompletar para as APIs nativas do JavaScript e do Fluig Plataforma.
Utilize o atalho do teclado CTRL + Barra de espaço para forçar a exibição do autocompletar no Eclipse ou Fluig Studio.
![](..\..\images\autocomplete_javscript.png)
![](..\..\images\autocomplete_ftl.gif)
# Exportar componente para o servidor Fluig
A partir deste momento é possível gerar o pacote e instalar o componente no servidor, ou seja, fazer o *deploy*.
- Selecionar a pasta do *widget* ou *layout* que será exportado e clicar sobre ela com o botão direito do *mouse*.
- Acionar ***Export*...**
- Selecionar a opção **Exportar para servidor Fluig** e acionar ***Next**.*
- Selecionar o servidor desejado dentre os servidores cadastrados no Eclipse ou Fluig Studio.
- Acionar ***Finish***.
Após a exportação, o componente estará disponível para utilização na [criação](http://tdn.totvs.com/pages/viewpage.action?pageId=234455933) e [edição](http://tdn.totvs.com/pages/viewpage.action?pageId=234455936) de páginas do Fluig Plataforma.
![](..\..\images\deploy_widget.gif)
Third Party Trademarks
*JavaScript is a trademark of Oracle Corporation.*
*Firefox and Mozilla are registered trademarks of the Mozilla Foundation.*
*Google, Android and Google Chrome are trademarks of the Google Inc.*
*Oracle, Java and [OpenOffice.org](http://OpenOffice.org) are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.*
*Red Hat and JBoss are registered trademarks of Red Hat, Inc. in the United States and other countries.*
*Any other third party trademarks are the property of their respective owners.*