Histórico da Página
Aviso |
---|
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.
Informações |
---|
|
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.
Informações |
---|
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. |
Bloco de código | ||||
---|---|---|---|---|
| ||||
define([
'totvs-custom'
], function (custom) {
'use strict';
function customerCustomService(customService) {
var service;
|
Exemplo de Customização:
Exemplo de Customização:
Considerando a seguinte tela, sem customização:
Como é uma pagina do estilo lista, e para permitir que seja customizada devemos definir o HTML da seguinte forma:
Bloco de código | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
<totvs-page type="list" totvs-custom-element="customPage"> <totvs-page-breadcrumb> <breadcrumb link="#/">Home</breadcrumb> <breadcrumb link="#/">Sample</breadcrumb> <breadcrumb>{{'l-country' | i18n}}</breadcrumb> </totvs-page-breadcrumb> <totvs-page-header> <totvs-page-header-title title="{{'l-country' | i18n}}" total="{{controller.listOfcountryCount}}"></totvs-page-header-title> ... |
Neste exemplo foi definido que quando a tela for apresentada, a customização será chamada pelo evento customPage, se apenas a diretiva for incluida no HTML sem valor, o evento chamado será customElement.
Como tambem pode ser necessária a customização da lista, que está definida com a diretiva ng-repeat, isso implica que os elementos controlados pelo ng-repeat não existem até que os dados relativos ao ng-repeat existam, por isso para todos os ng-repeat's que precisam de customização, tambem deverão definir o ponto de customização, por exemplo:
Bloco de código | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
<totvs-page-content> <totvs-list-item id="country{{country.id}}" class="tag-2" ng-repeat="country in controller.listOfcountry" 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"> <totvs-list-item-header> customListItem : function (params, element) { <totvs-list-item-title title="{{country.id}} - {{country.name}}" link="#/thf/html-sample/country/detail/{{ country.id }}"></totvs-list-item-title> |
Neste ponto definimos o evento da customização que sera usado como customListItem, da mesma forma, se não for informado será assumido o evento customElement.
Para eventos que serão chamados pelos controllers da tela, o controller deverá utilizar o serviço de customização definido na biblioteca totvs-custom que deverá ser adicionada como requisito na definição para o requireJS
Bloco de código | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
define(['index',
'components',
'totvs-custom',
], function(index) {
// *************************************************************************************
// *** FACTORIES
// *************************************************************************************
countryFactory.$inject = ['$totvsresource'];
function countryFactory($totvsresource) {
... |
Na definição do controller deverá ser injetada a factory do serviço de customização 'customization.generic.Factory', conforme o exemplo abaixo:
Bloco de código | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
// *************************************************************************************
// *** CONTROLLER - LIST
// *************************************************************************************
countryListController.$inject = ['$rootScope', '$scope', 'totvs.app-main-view.Service',
'html-sample.country.Service', 'customization.generic.Factory'];
function countryListController($rootScope, $scope, appViewService, countryService, customizationService) {
var _self = this;
|
E no ponto onde a customização deverá ser chamada, devemos utilziar o serviço customizationService:
Bloco de código | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||
// *********************************************************************************
// *** Control Initialize
// *********************************************************************************
this.init = function() {
if (appViewService.startView('l-country', 'framework.country-list.Control', _self)) {
}
this.search(false);
customizationService.callEvent('html-sample.country', 'initEvent', _self);
}
|
Neste exemplo, no metodo init do controller, foi colocado o ponto de customização com o evento initEvent, onde no parametro é enviado o _self (o proprio controller), o primeiro parametro é o identificador do serviço de customização que será explicado a seguir.
Identificador do serviço de customização
Para customização funcionar corretamente, utilizamos o recurso de injeção de dependencia do angular para definir uma factory cada customização e utilizamos essa factory nos eventos de customização, mas como a customização é opcional, porem a definição da factory não, a aplicação centralizadora quando não encontra o script de customização, define essa factory automaticmaente com o nome seguinte o padrão:
custom.<contexto da tela>.<nome da tela>
Que no nosso exemplo é: custom.html-sample.country onde html-sample é o contexto da tela, country é o nome da tela.
Por padrão as telas ficam em um contexto do WebContainer (no nosso exemplo html-sample) e nesse contexto temos o diretório html e dentro deste country (nome da tela) e dentro deste o country.js (script inicial da tela)
A customização para as telas devem ser colocadas todas, no contexto custom, em uma pasta com o nome do contexto da tela (html-sample) e o script de customização com o nome da tela (country.js)
Então para este tela customizada temos a seguinte estrutura:
Bloco de código | ||
---|---|---|
| ||
[Pasta] WebContainer/thf/custom
[Pasta] WebContainer/thf/custom/html-sample
[Script] WebContainer/thf/custom/html-sample/country.js
[Pasta] WebContainer/thf/html-sample
[Pasta] WebContainer/thf/html-sample/html
[Pasta] WebContainer/thf/html-sample/html/country
[Script] WebContainer/thf/html-sample/html/country/country.js
[Script] WebContainer/thf/html-sample/html/country/country-services.js
[HTML] WebContainer/thf/html-sample/html/country/country.list.html
[HTML] WebContainer/thf/html-sample/html/country/country.detail.html
[HTML] WebContainer/thf/html-sample/html/country/country.edit.html |
Customização exemplo:
Como exemplo para tela de paises, vamos utilizar o seguinte arquivo de customização comentado.
...
}
};
// 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);
}); |
Bloco de código | ||||
---|---|---|---|---|
| ||||
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);
}); |
Informações |
---|
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>
Aviso |
---|
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:
Bloco de código | ||
---|---|---|
| ||
<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".
Bloco de código | ||
---|---|---|
| ||
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.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<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).
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
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).
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
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
| ||||||||
Bloco de código | ||||||||
| ||||||||
define(['index', 'totvs-custom'], function(index) { countryCustomService.$inject = ['customization.generic.Factory']; function countryCustomService(customService) { service = { // metodos para cada evento de customização // metodo do evento customizado no controller no metodo init. initEvent : function (params) { // na chamada do callEvent foi passado o proprio controller, como o controller é acessivel para a tela // a tela pode fazer binding para o novo atributo criado abaixo. params.epcValue = "Este valor foi definido na epc e injetado no controler desta tela!!!"; // na chamada do evento, a customização pode retornar um valor que chega até a chamada no controller. return "OK"; }, // metodo do evento customizado na pagina na tag HTML com totvs-custom-element="customPage" customPage : function (params, element) { // utilizamos a API do jQuery para encontrarmos os elementos que queremos customizar na pagina // procuramos uma elmento que tem a class "title" filho de um elemento com a class "page-head" var title = element.find(".page-head .title"); // utilizando a API do jQuery podemos adicionar HTML estatico a um elemento title.append('<div style="background-color: red; font-style: italic; font-size: 24px; color: yellow;">' + 'Esta tela é customizável</div>'); // ou podemos adicionar HTML dinamico com bindings do angular, utilizando o scope da pagina // com acesso ao controller, inclusive aos atributos que foram incluidos por customização. // tambem é possivel associar eventos que chamam o controller var html = '<div style="background-color: black; font-size: 24px; color: green;">' + 'E posso compilar com os bindings do angular, ' + 'a lista tem {{controller.listOfcountry.length}} itens' + '<div style="background-color : brown; color: white;">{{controller.epcValue}}</div></div>' // o metodo compileHTML do customService permite que o HTML seja compilado contra o scope da tela var compiledHTML = customService.compileHTML(params, html); // e este HTML compilado pode ser adicionado ao elemento utilizando a API do jQuery title.append(compiledHTML); }, // metodo 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 = element.find('div[title]:first'); // definimos a customização que será adicionada ao elemento. var html = '<span style="background-color: yellow"> - <a target="_blank" href="http://pt.wikipedia.org/wiki/{{country.name}}">Este link para Wikipedia também e uma customização</a></span>'; // como o HTML tem binding para o scopo do angular, precisamos compilar o HTML var 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); // e este HTML compilado pode ser adicionado ao elemento utilizando a API do jQuery title.append(compiledHTML); } }; // todas as customizações devem estender o customService para as chamadas ocorrerem de forma correta. item.append(compiledField); } }; angular.extend(service, customService); return service; } // conforme definido, o nome da factory é "custom." mais o contexto e nome da tela. index.register.factory('custom.html-sample.country', countryCustomService } customerCustomService.$inject = ['customization.generic.Factory']; custom.register(customerCustomService); }); |
...
Resultado da customização
...