A documentação se refere a versões do THF (até o release 12.1.11) ou produtos TOTVS que utilizam o RequireJS.
Procure a Fábrica de Software da TOTVS para suporte a customizações.
O TOTVS HTML Framework permite que as telas desenvolvidas sejam customizadas para atender a necessidade de cada cliente em específico.
Antes de buscar o javascript da tela padrão, a aplicação centralizadora procura por um arquivo javascript de customização, caso encontre o arquivo, é registrado um serviço com a implementação dos pontos de customização, caso o script de customização não seja encontrado, será exibida uma mensagem de erro no console.
Deve-se criar um módulo chamado "custom" para os programas customizados.
Só é possível customizar um programa padrão caso o mesmo seja "preparado" para isso antes (view e/ou controller).
Pontos de customização
A view deve ter elementos que serviram como pontos de customização definidos pela diretiva Totvs Custom Element que iram disparar um método do serviço responsável pela customização, para esse método é passado o escopo e o elemento da diretiva.
É possível configurar o evento que será chamado pela customização, caso não seja definido um método será chamado o evento padrão "customElement", também é possível definir o nome do serviço através do atributo "totvs-custom-service", caso não seja definido o serviço, será gerado um nome baseado no contexto do programa.
Além da view, o controller também pode implementar pontos de customização utilizando o serviço genérico de customização "customization.generic.Factory" através do método "callEvent", onde deve-se passar o serviço, o nome do método de customização, os parâmetros e a referência do elemento a ser customizado (caso precise).
Serviço de customização
Existem duas formas de criar um serviço de customização, no primeiro exemplo o nome e registro do serviço é gerenciado pelo serviço genérico de customização e não há necessidade de usar o atributo "totvs-custom-service", já no segundo exemplo, o nome e registro do serviço ficam por conta do desenvolvedor e o atributo "totvs-custom-service" passa a ser obrigatório.
Independente da forma que é criado, os serviço de customização devem estender o serviço "customization.generic.Factory" através da função angular.extend.
define([ 'totvs-custom' ], function (custom) { 'use strict'; function customerCustomService(customService) { var service; service = { // metodos para cada evento de customização // metodo do evento customizado no controller no metodo init. initEvent: function (params) { ... return "OK"; }, // metodo do evento customizado na pagina na tag HTML com totvs-custom-element="customPage" customPage: function (params, element) { ... }, // metodo do evento customizado na pagina na tag HTML com totvs-custom-element="customListItem" customListItem : function (params, element) { ... } }; // Estende o serviço customization.generic.Factory angular.extend(service, customService); return service; } customerCustomService.$inject = ['customization.generic.Factory']; // Registra o serviço de customização através do serviço genérico de customização custom.register(customerCustomService); });
define([ 'index', 'totvs-custom' ], function (index) { 'use strict'; function customerCustomService(customService) { var service; service = { // metodos para cada evento de customização // metodo do evento customizado no controller no metodo init. initEvent: function (params) { ... return "OK"; }, // metodo do evento customizado na pagina na tag HTML com totvs-custom-element="customPage" customPage: function (params, element) { ... }, // metodo do evento customizado na pagina na tag HTML com totvs-custom-element="customListItem" customListItem : function (params, element) { ... } }; // Estende o serviço customization.generic.Factory angular.extend(service, customService); return service; } customerCustomService.$inject = ['customization.generic.Factory']; // Registra o serviço com um nome específico index.register.factory('custom.customization.customer.factory', customerCustomService); });
Todo serviço de customização deve ter como dependência a biblioteca totvs-custom na definição para o requireJS.
Identificador do serviço de customização
Caso o desenvolvedor não queira informar um nome para o serviço de customização, será criado um serviço com o nome no seguinte padrão:
custom.<produto>.<modulo>.<programa>
Caso o desenvolvedor deseje dar um nome ao serviço de customização deve seguir o seguinte padrão:
custom.<nome_servico>
Nos dois casos, ao fazer referência ao serviço de customização não deve ser usado o prefixo "custom.". Caso o nome do serviço seja "custom.customization.customer.factory", então deve ser passado para o atributo "totvs-custom-service" apenas como "customization.customer.factory".
Hierarquia dos arquivos
Os arquivos de customização devem ser criados em um módulo nomeado como "custom", esse módulo conterá todas as customizações do produto separados por pastas representando seus respectivos módulos.
Para que a customização funcione corretamente é necessário que os arquivos sejam criados na seguinte estrutura:
<WebContainer> <produto> custom <modulo> <programa>.js <modulo> html <programa> <programa>.js <programa>.factory.js <programa>.list.html <programa>.list.controller.js <programa>.detail.html <programa>.detail.controller.js <programa>.edit.html <programa>.edit.controller.js *.* *.*
Exemplo de uma aplicação real onde nosso produto é chama-se "thf", nosso módulo é o "demo", e nosso programa que será customizado será o "customer".
public thf custom demo customer.js demo html customer customer.js customer.factory.js customer.list.html customer.list.controller.js customer.detail.html customer.detail.controller.js customer.edit.html customer.edit.controller.js *.*
Exemplo
Nesse exemplo vamos customizar o programa "customer" do módulo "demo".
Definindo pontos de customização na view
Para permitir que uma view seja customizada devemos incluir pontos de customização nessa view.
O arquivo thf\demo\html\customer\customer.list.html terá dois pontos de customização, um na diretiva totvs-page e o outro na diretiva totvs-list-item.
Na diretiva totvs-page será disparado o método customPageList do serviço de customização e na diretiva totvs-list-item será disparado o método customListItem, caso nenhum método seja especificado será disparado o método customPage.
Caso seja criado um serviço de customização com um nome definido pelo desenvolvedor, o atributo totvs-custom-service deve ser incluído nas mesma diretiva que vai receber a customização.
<totvs-page type="list" totvs-custom-element="customPageList"> <totvs-page-navbar> <totvs-page-breadcrumb> <breadcrumb link="#/">{{ 'l-home' | i18n }}</breadcrumb> <breadcrumb>{{ 'l-menu-customer' | i18n }}</breadcrumb> </totvs-page-breadcrumb> <totvs-page-header> <totvs-page-header-title title="{{'l-customers' | i18n}}" total="{{controller.recordsCount}}"></totvs-page-header-title> ... </totvs-page-header> ... </totvs-page-navbar> <totvs-page-content> <totvs-list-item ng-repeat="customer in controller.records | filter : controller.searchText" totvs-custom-element="customListItem"> <totvs-list-item-header> ... </totvs-list-item-header> <totvs-list-item-content> ... <totvs-list-item-content> </totvs-list-item> ... </totvs-page-content> ... </totvs-page>
Definindo ponto de customização no controller
Para permitir que um controller seja customizado, é preciso adicionar pontos de customização dentro do controller.
O arquivo thf\demo\html\customer\customer.list.controller.js terá um ponto de customização logo após fazer a carga inicial dos dados, para isso é necessário primeiro injetar o serviço "customization.generic.Factory" no controller e chamar o método callEvent passando como parâmetro o nome do serviço de customização, o nome do método a ser executado, os parâmetros e o elemento que deseja customizar (caso exista).
define([ 'index', ... ], function (index) { 'use strict'; var customersListController = function ($rootScope, appViewService, customerService, customizationFactory) { // ********************************************************************************* // *** Variables // ********************************************************************************* var self = this; self.records = []; self.recordsCount = 0; ... // ********************************************************************************* // *** Control Initialize // ********************************************************************************* self.init = function () { appViewService.startView($rootScope.i18n('l-customer') + ' (Customizado)', 'demo.customer.list.controller', self); self.loadRecords(false); // Dispara o método 'initEvent' do serviço de customização do 'thf.demo.customer' passando o controller como parâmetro customizationService.callEvent('thf.demo.customer', 'initEvent', self); }; ... }; customersListController.$inject = [ '$rootScope', 'totvs.app-main-view.Service', 'customization.customer.factory', // Serviço de customização 'customization.generic.Factory' ]; index.register.controller('demo.customer.list.controller', customersListController); });
Criando serviço de customização
É necessário criar um arquivo js para definir o serviço de customização dentro do módulo custom (thf/custom/demo/customer.js).
define([ 'totvs-custom' ], function (custom) { 'use strict'; function customerCustomService(customService) { var service; service = { // métodos para cada evento de customização // método do evento customizado no controller initEvent: function (params) { // na chamada do callEvent foi passado o próprio controller, como o controller é acessível para a tela // a tela pode fazer binding para o novo atributo criado abaixo. params.customInitValue = "Este valor foi definido no serviço de customização e injetado no controller desta tela!!!"; // na chamada do evento, a customização pode retornar um valor que chega até a chamada no controller. return "OK"; }, // método do evento customizado na pagina na tag HTML com totvs-custom-element="customPageList" customPageList: function (params, element) { // utilizamos a API do jQuery para encontrarmos os elementos que queremos customizar na pagina // procuramos um elemento que tem a class "page-head" var title, html, compiledHTML; title = element.find(".page-head"); // utilizando a API do jQuery podemos adicionar HTML estático a um elemento title.append('<div style="background-color: red; font-style: italic; font-size: 24px; color: yellow;">' + 'Esta tela é <a href="http://tdn.totvs.com/pages/viewpage.action?pageId=185738044" target="_blank">customizável</a>' + '</div>'); // ou podemos adicionar HTML dinâmico com bindings do angular, utilizando o scope da pagina // com acesso ao controller, inclusive aos atributos que foram incluídos por customização. // também é possível associar eventos que chamam o controller html = '<div style="background-color: black; font-size: 24px; color: green;">' + 'E posso compilar com os bindings do angular, a lista tem {{controller.recordsCount}} itens' + '<div style="background-color : brown; color: white;">{{controller.customInitValue}}</div></div>'; // o método compileHTML do customService permite que o HTML seja compilado contra o scope da tela compiledHTML = customService.compileHTML(params, html); // e este HTML compilado pode ser adicionado ao elemento utilizando a API do jQuery title.append(compiledHTML); }, // método do evento customizado na pagina na tag HTML com totvs-custom-element="customListItem" // como aquele elemento é controlado por um ng-repeat, // esta customização é chamada para cada item que é renderizado na lista customListItem : function (params, element) { // primeiro encontramos o elemento que queremos customizar var title, item, html, compiledHTML, compiledField; title = element.find('div[title]:first'); // definimos a customização que será adicionada ao elemento. html = '<span style="background-color: yellow">' + ' - <a target="_blank" href="http://tdn.totvs.com/display/tec/TOTVS+%7C++HTML+Framework">' + 'Este link para TDN também e uma customização</a>' + '</span>'; // como o HTML tem binding para o scopo do angular, precisamos compilar o HTML compiledHTML = customService.compileHTML(params, html); // e este HTML compilado pode ser adicionado ao elemento utilizando a API do jQuery title.append(compiledHTML); item = element.find('.item-info .row'); // definimos a customização que será adicionada ao elemento, nesse caso incluímos 2 novos campos para exibição html = '<totvs-list-item-info title="Campo customizado #1" value="Valor customizado #1"></totvs-list-item-info>' + '<totvs-list-item-info title="Campo customizado #2" value="Valor customizado #2"></totvs-list-item-info>'; compiledField = customService.compileHTML(params, html); item.append(compiledField); } }; angular.extend(service, customService); return service; } customerCustomService.$inject = ['customization.generic.Factory']; custom.register(customerCustomService); });
Resultado da customização
3 Comentários
Adilson de Oliveira
Observações importantes e complementares:
1: A pasta custom.war, onde serão depositados os arquivos das customizações html deve estar dentro da pasta deploy do jboss.
2: É necessário reiniciar o jboss somente após criar a pasta custom.war, para atualização de arquivos dentro desta pasta
não é necessário reiniciar o jboss, porém é importante limpar o cache do navegador para cada arquivo atualizado.
3: A url das interfaces já existentes que forem customizadas continuam iguais, a diferença é que a interface carregará o arquivo de customização .js
antes do arquivo .js padrão da interface e injetará as customizações na interface padrão.
Usuário desconhecido (jhosef.carvalho)
Pontos 1 e 2 são específicos do produto Datasul e o ponto 3 é está completamente correto.
Obrigado pelo complemento.
Cleberson Paulo De Andrade Silva
Apenas complementando as informações passadas pelo Adilson no ponto 1.
Além de se criar a pasta custom.war, existe a necessidade de criar a sub-pasta WEB-INF (em MAIÚSCULO) com os arquivos: web.xml e jboss-web.xml.
No arquivo web.xml, deve conter o seguinte conteúdo:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Custom</display-name>
</web-app>
No arquivo jboss-web.xml, deve conter o seguinte conteúdo:
<jboss-web>
<context-root>dts/custom</context-root>
</jboss-web>