Árvore de páginas

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.
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.

A customização no framework HTML funciona da seguinte forma: 

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
  • 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.

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
titleServiço de customização #1
linenumberstrue
define([
    'totvs-custom'
], function (custom) {

    'use strict';

    function customerCustomService(customService) {

        var service;

Exemplo de Customização:

A customização no framework HTML funciona da seguinte forma: 
Antes de buscar o javascript da tela, a aplicação centralizadora busca carregar o javascript da customização, que deve registrar um serviço do angular com a implementação dos pontos de customização, caso o script de customização não seja encontrado, o serviço angular é criado automaticamente sem implementação dos pontos.
A tela pode ter pontos de customização, definidos pela diretiva totvs-custom-element que ira chamar um metodo definido no serviço definido do script de customização, passando o scopo e o elemento da diretiva, a diretiva permite configurar o evento que será chamado na customização e permite que o nome do serviço seja definido caso não seja o padrão explicado mais abaixo no exemplo.
A logica do controller da tela tambem pode implementar pontos de customização utilizando o serviço de customização, utilizando o metodo callEvent, onde pode-se passar qualquer parametro para a customização e tratar o retorno.

Exemplo de Customização:

Considerando a seguinte tela, sem customização:

Image Removed

Como é uma pagina do estilo lista, e para permitir que seja customizada devemos definir o HTML da seguinte forma:

Bloco de código
languagexml
firstline1
titleExemplo
linenumberstrue
collapsetrue
 <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
languagexml
firstline1
titleExemplo
linenumberstrue
collapsetrue
	<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
languagejs
firstline1
titleExemplo
linenumberstrue
collapsetrue
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
languagejs
firstline1
titleExecmplo
linenumberstrue
collapsetrue
	// *************************************************************************************
	// *** 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
languagejs
firstline1
titleExemplo
linenumberstrue
collapsetrue
		// *********************************************************************************
		// *** 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
titleEstrutura
[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
titleServiço de customização #2
linenumberstrue
 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
titleEstrutura
<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
titleEstrutura
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".

Image Added

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
languagexml
firstline1
titleExemplo
linenumberstrue
<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
languagejs
firstline1
titleExecmplo
linenumberstrue
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
languagejs
firstline1
titleExemplo de Customização
linenumberstrue
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&eacute;m e uma customiza&ccedil;&atilde;o</a>' +
                        '</span>';


                // como o HTML tem binding para o scopo do angular, precisamos compilar o HTML
               
Bloco de código
languagejs
firstline1
titleExemplo de Customização
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 &eacute; customiz&aacute;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&eacute;m e uma customiza&ccedil;&atilde;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

...

Image Removed

Image Added