ti-enxame.com

AngularJS, essa maneira de usar o serviço é boa?

eu tenho este HTML:

<p>Hello {{name}}</p>

e o controlador é:

function myCtrl(scope, service) {
    scope.name = service.getUsername(); // service.getUsername() return "World!"
}
myCtrl.$inject = ['$scope', 'originalService'];

O serviço funciona bem, então não colo o código aqui ... Nesse caso, o resultado é "Olá, mundo!" Alterei o HTML dessa maneira:

<p>Hello {{service.getUsername()}}</p>

Mas isso não funciona.

Eu mudei o controlador:

function myCtrl(scope, service) {
    scope.ser = service;
}
myCtrl.$inject = ['$scope', 'originalService'];

e então o HTML

<p>Hello {{ser.getUsername();}}</p>

Isso funciona!

Então, minha pergunta é:

Essa é a única maneira de usar as funções de um serviço diretamente no HTML, ou estou perdendo alguma coisa?

28
Bruno

Os modelos AngularJS podem chamar apenas funções disponíveis em um escopo. Portanto, qualquer que seja sua abordagem, você precisa ter sua função em um escopo.

Se você deseja que as funções do seu serviço sejam diretamente invocáveis ​​a partir de um modelo, você tem várias opções:

O que você tentou - ou seja, expõe todo o serviço em um escopo :

$scope.service = service;

e depois em um modelo:

<p>Hello {{service.getUsername();}}</p>

É uma linha em um controlador e disponibiliza todos os métodos de serviço em um escopo e, portanto, em modelos.

Exponha os métodos um por um

para ter controle preciso sobre o que é exposto:

$scope.getUsername = service.getUsername;

e depois em um modelo:

<p>Hello {{getUsername();}}</p>

Isso requer mais métodos de exposição do trabalho, mas fornece controle refinado sobre o que é exposto.

Expor métodos de proxy :

$scope.getMyUsername = function() {
   //pre/post processing if needed 
   return service.getUsername();
};

Você pode usar qualquer um desses métodos ou combiná-los e combiná-los, mas no final do dia, uma função deve terminar em um escopo (diretamente ou através de outro objeto exposto em um escopo).

61
pkozlowski.opensource

Outra maneira de fazer isso:

Exponha o serviço em $ rootScope :

$rootScope.service = service;

e depois em um modelo:

<p>Hello {{service.getUsername();}}</p>

Você pode fazer isso em app.run e obterá o serviço em todas as visualizações do seu aplicativo. Você pode usar esse método para serviços de autenticação.

14
Juancarlos Rodríguez

Outra maneira de expor seu serviço dentro do seu escopo $ seria adicionar um ponteiro de função ao seu método de serviço/objeto de dados.

scope.serviceData = service.data;
// Or
scope.getServiceData = service.getData;

Na sua visualização, você pode invocá-lo usando parênteses.

<input ng-model="serviceData().key" />
// Or
<input ng-model="getServiceData().key" />
// Or
{{getServiceData().key}}

Pessoalmente, gosto dessa abordagem e atualmente a estou usando para manter várias visualizações sincronizadas com os mesmos dados. Isso traz alguns problemas, conforme explicado aqui: AngularJS. Prática recomendada a respeito da ligação de dados bidirecional adequada de um serviço

Quanto à exposição a muitos dados, atualmente estou tentando fazer algo assim.

// Within your view.
{{getServiceDataByKey('key')}}

// In your controller.
scope.getServiceDataByKey = service.getServiceDataByKey;

// In your service.
getServiceDataByKey : function (key) {
   return dataObject[key];
}

A razão pela qual estou fazendo isso é que queremos manter os controladores o mais limpos possível e ter todos os nossos dados em um local centralizado. Além disso, a maioria dos dados dentro do serviço deve ser exposta.

1
ngr