Gostaria de adicionar algumas funções utilitárias ao meu aplicativo AngularJS. Por exemplo:
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
É a melhor maneira de fazer isso para adicioná-los como um serviço? Pelo que li, posso fazer isso, mas gostaria de usá-los nas minhas páginas HTML, por isso ainda é possível se eles estiverem em um serviço? Por exemplo, posso usar o seguinte:
<button data-ng-click="doSomething()"
data-ng-disabled="isNotString(abc)">Do Something
</button>
Alguém pode me dar um exemplo de como eu poderia adicioná-los. Devo criar um serviço ou existe alguma outra maneira de fazê-lo. O mais importante é que eu gostaria dessas funções utilitárias em um arquivo e não combinadas com outra parte da configuração principal.
Entendo que existem algumas soluções, mas nenhuma é tão clara.
Solução 1 - Proposta pela Urban
$scope.doSomething = ServiceName.functionName;
O problema aqui é que tenho 20 funções e dez controladores. Se eu fizesse isso, significaria adicionar muito código a cada controlador.
Solução 2 - Proposta por mim
var factory = {
Setup: function ($scope) {
$scope.isNotString = function (str) {
return (typeof str !== "string");
}
A desvantagem disso é que, no início de cada controlador, eu teria uma ou mais dessas chamadas de instalação para cada serviço que passasse o escopo $.
Solução 3 - Proposta pela Urban
A solução proposta pela urban de criar um serviço genérico parece boa. Aqui está a minha configuração principal:
var app = angular
.module('app', ['ngAnimate', 'ui.router', 'admin', 'home', 'questions', 'ngResource', 'LocalStorageModule'])
.config(['$locationProvider', '$sceProvider', '$stateProvider',
function ($locationProvider, $sceProvider, $stateProvider) {
$sceProvider.enabled(false);
$locationProvider.html5Mode(true);
Devo adicionar o serviço genérico a isso e como posso fazê-lo?
Respostas:
EDIT 1/7/15:
Eu escrevi essa resposta há muito tempo e não acompanho muito o angular há um tempo, mas parece que essa resposta ainda é relativamente popular, então eu gostaria de salientar que alguns dos pontos @nicolas faz abaixo são bons. Por um lado, injetar $ rootScope e anexar os auxiliares impedirá que você os adicione em todos os controladores. Além disso - concordo que, se o que você está adicionando deve ser considerado como serviços angulares OU filtros, eles devem ser adotados no código dessa maneira.
Além disso, a partir da versão atual 1.4.2, o Angular expõe uma API "Provider", que pode ser injetada em blocos de configuração. Veja estes recursos para mais:
https://docs.angularjs.org/guide/module#module-loading-dependencies
Injeção de valor AngularJS dentro do module.config
Eu não acho que vou atualizar os blocos de código reais abaixo, porque atualmente não estou usando ativamente o Angular e não quero arriscar uma nova resposta sem me sentir confortável por estar realmente em conformidade com o novo melhor práticas. Se alguém quiser, por todos os meios, vá em frente.
EDIT 2/3/14:
Depois de pensar sobre isso e ler algumas das outras respostas, acho que prefiro uma variação do método apresentado por @Brent Washburne e @Amogh Talpallikar. Especialmente se você estiver procurando por utilitários como isNotString () ou similar. Uma das vantagens claras aqui é que você pode reutilizá-las fora do seu código angular e usá-las dentro da sua função de configuração (o que você não pode fazer com os serviços).
Dito isto, se você está procurando uma maneira genérica de reutilizar o que deveria ser adequadamente os serviços, acho que a resposta antiga ainda é boa.
O que eu faria agora é:
app.js:
controller.js:
Então, na sua parcial, você pode usar:
Antiga resposta abaixo:
Talvez seja melhor incluí-los como um serviço. Se você for reutilizá-los em vários controladores, incluí-los como um serviço impedirá que você precise repetir o código.
Se você deseja usar as funções de serviço em seu html parcial, adicione-as ao escopo desse controlador:
$scope.doSomething = ServiceName.functionName;
Então, na sua parcial, você pode usar:
Aqui está uma maneira de manter tudo organizado e livre de muitos aborrecimentos:
Separe seu controlador, serviço e código / configuração de roteamento em três arquivos: controllers.js, services.js e app.js. O módulo da camada superior é "app", que possui app.controllers e app.services como dependências. Em seguida, app.controllers e app.services podem ser declarados como módulos em seus próprios arquivos. Essa estrutura organizacional foi retirada da Angular Seed :
app.js:
services.js:
controller.js:
Então, na sua parcial, você pode usar:
Dessa forma, você adiciona apenas uma linha de código a cada controlador e pode acessar qualquer uma das funções de serviço sempre que esse escopo estiver acessível.
fonte
Chegando neste tópico antigo, eu queria enfatizar que
1 °) as funções de utilidade podem (devem?) Ser adicionadas ao rootcope via module.run. Não há necessidade de instanciar um controlador de nível raiz específico para esse fim.
2 °) Se você organizar seu código em módulos separados, deverá utilizar serviços angulares ou de fábrica e injetá-los na função passada para o bloco de execução, como segue:
3 °) Meu entendimento é que, nas visualizações, na maioria dos casos, você precisa dessas funções auxiliares para aplicar algum tipo de formatação às seqüências de caracteres exibidas. O que você precisa neste último caso é usar filtros angulares
E se você estruturou alguns métodos auxiliares de baixo nível em serviços angulares ou de fábrica, basta injetá-los no construtor de filtros:
E na sua opinião:
fonte
run
tempo. E o tempo de configuração? Não precisamos de utilitários por aí?Entendi corretamente que você apenas deseja definir alguns métodos utilitários e disponibilizá-los em modelos?
Você não precisa adicioná-los a todos os controladores. Apenas defina um único controlador para todos os métodos utilitários e conecte-o a <html> ou <body> (usando a diretiva ngController). Quaisquer outros controladores que você anexar em qualquer lugar em <html> (que significa qualquer lugar, período) ou <body> (em qualquer lugar, exceto <head>) herdarão esse escopo $ e terão acesso a esses métodos.
fonte
<div class="main-container" ng-controller="UtilController as util">
então, em qualquer vista interna:<button ng-click="util.isNotString(abc)">
A maneira mais fácil de adicionar funções utilitárias é deixá-las no nível global:
Então, a maneira mais simples de adicionar uma função de utilidade (a um controlador) é atribuí-la
$scope
, assim:Então você pode chamar assim:
ou assim:
EDITAR:
A pergunta original é se a melhor maneira de adicionar uma função de utilitário é através de um serviço. Eu digo não, se a função for simples o suficiente (como o
isNotString()
exemplo fornecido pelo OP).O benefício de escrever um serviço é substituí-lo por outro (via injeção) para fins de teste. Levado ao extremo, você precisa injetar todas as funções de utilidade em seu controlador?
A documentação diz para simplesmente definir o comportamento no controlador (como
$scope.double
): http://docs.angularjs.org/guide/controllerfonte
Aqui está um método simples, compacto e fácil de entender que eu uso.
Primeiro, adicione um serviço em seus js.
Em seguida, no seu controlador, injete seu objeto auxiliar e use qualquer função disponível com algo como o seguinte:
fonte
Você também pode usar o serviço constante como tal. Definir a função fora da chamada constante também permite que ela seja recursiva.
fonte
Por que não usar a herança do controlador, todos os métodos / propriedades definidos no escopo do HeaderCtrl estão acessíveis no controlador dentro da ng-view. $ scope.servHelper está acessível em todos os seus controladores.
fonte