2013-02-23 13 views
28

Ho questo HTML:AngularJS, questo modo di utilizzare il servizio è buono?

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

e il controllore è:

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

Il servizio funziona bene, quindi non mi incollare il codice qui ... In questo caso il risultato è "! Ciao mondo" ho cambiato il codice HTML in questo modo:

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

Ma questo non funziona.

ho cambiato il controllore:

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

e poi il codice HTML

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

Questo funziona!

Quindi la mia domanda è:

È questo l'unico modo per utilizzare le funzioni di un servizio direttamente nel codice HTML, o mi manca qualcosa?

risposta

61

I modelli AngularJS possono solo richiamare funzioni disponibili su un ambito. Quindi, qualunque approccio tu abbia, devi avere la tua funzione su un ambito.

Se si desidera funzioni del servizio di essere direttamente richiamabile da un modello che hai diverse opzioni:

quello che hai provato - vale a dire, espongono l'intero servizio a parità di area:

$scope.service = service; 

e poi in un modello:

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

questo i s one-liner in un controller e rende disponibili tutti i metodi di servizio su un ambito e quindi su modelli.

Esporre metodi uno per uno

di avere un controllo preciso su ciò che viene esposto:

$scope.getUsername = service.getUsername; 

e poi in un modello:

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

Questo richiede più lavoro esponendo metodi ma ti dà un controllo preciso su ciò che viene esposto.

Expose proxing metodi:

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

è possibile utilizzare uno qualsiasi di questi metodi o di mescolare e combinare, ma alla fine della giornata una funzione deve finire su un ambito (sia direttamente o tramite un altro oggetto esposto su un ambito).

+4

Buona risposta. Eviterei comunque di aggiungere l'intero oggetto servizio all'ambito, se non si tratta di un tipo di servizio di visualizzazione e il modello richiede tutte le funzionalità del servizio. In genere, si desidera aggiungere solo i dati/le funzioni sull'ambito di cui il modello necessita e nulla più. –

+0

@AndersEkdahl Sono d'accordo, probabilmente non si vuole usare questo metodo molto spesso. Ma immagino che tutto dipenda dal servizio. Sto solo presentando le opzioni qui, ci sono diversi compromessi da considerare. –

+0

@ pkozlowski.opensource ringrazia per la risposta – Bruno

1

Un altro modo per esporre il servizio all'interno di $ scope è quello di aggiungere un puntatore a funzione al metodo di servizio/oggetto dati.

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

All'interno della vista è possibile quindi richiamarlo utilizzando le parentesi.

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

Personalmente mi piace questo approccio e attualmente lo sto utilizzando per mantenere più viste sincronizzate con gli stessi dati. Fa sorgere alcuni problemi però come spiegato qui: AngularJS. Best practice concerning proper two way data binding from a service

Per quanto riguarda l'esposizione a molti dati sto attualmente cercando di fare qualcosa di simile.

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

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

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

Il motivo per cui sto facendo questo è che vogliamo mantenere i controllori più pulito possibile e avere tutti i nostri dati in un unico luogo centralizzato. Anche la maggior parte dei dati all'interno del servizio dovrebbe essere esposta.

13

Un altro modo per farlo:

Esporre il servizio sul $ rootScope:

$rootScope.service = service; 

e poi in un modello:

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

È possibile farlo su app.run e otterrai il servizio in tutte le visualizzazioni della tua app. È possibile utilizzare questo metodo per i servizi di autenticazione.

+7

È sporco. Lo adoro ! –

+0

Tieni presente che test come questo saranno interessanti ... –

Problemi correlati