2013-12-16 20 views
13

Sono così verde in Angular, non sono nemmeno sicuro che stia strutturando una ricerca per questo correttamente. L'intera direttiva e la terminologia del servizio mi stanno ancora confondendo, ma non è questa la mia domanda.AngularJS - Chiamare una funzione di controller da un servizio

Ho letto questo eccellente fronte serie di articoli alla parte posteriore: http://www.ng-newsletter.com/posts/beginner2expert-how_to_start.html

Quale è il motivo per cui io sono a questo punto della mia domanda. E perché so che la mia domanda riguarda più il rapporto tra servizi e controllori. Piuttosto che correlati alla sintassi.

Così qui è una panoramica dell'app:

ho un controller. Questo si spegne e ottiene una serie di dati della farm per l'utente che utilizza una chiamata AJAX in un file PHP e la visualizza sullo schermo usando il proprio $ scope.

var masterApp = angular.module('masterApp', ['myFilters','commonControls']); 

masterApp.controller('MasterCtrl', ['$scope','$http', '$filter', 'commonFarmSelector', 
    function($scope, $http, $filter, commonFarmSelector){ 

     ... 

     $scope.masterCtrl.loadFarmData = function(farmId) { 
      var postdata = { 
       "farmId":farmId 
      }; 

      $http.post('/service/farmproduction', postdata).success(function (data) { 
       // Do stuff with the $scope using data 
      } 
     } 

     $scope.masterCtrl.loadFarms(); 
} 

Vedrete che sto iniettando qualcosa chiamato "commonControls". Questo era un modulo che ho creato per contenere i controlli che saranno riutilizzati da più controller. In questo caso, un campo a discesa che contiene un elenco di aziende che l'utente ha accesso a (ottenuto anche da una chiamata AJAX):

var commonControlsApp = angular.module('commonControls', []); 

commonControlsApp.controller('farmSelectorCtrl', ['$scope', '$http',function($scope, $http) { 

    $scope.farmSelectorCtrl ={} 

    // Change entire farm view when a different farm is selected 
    $scope.farmSelectorCtrl.switchUserFarm = function() { 
     var farmId = $scope.farmSelectorCtrl.selectedUserFarm; 
     $scope.masterCtrl.loadFarms(farmId); // !!! Direct link to masterCtrl 
    }; 

    // Get a list of the user's farms 
    $http.post('/service/userfarms').success(function (data) { 
     $scope.farmSelectorCtrl.userFarms = data.getFarmsPerUserResult.farmIds; 
    }); 

}]); 

Questo funziona bene. Ma come puoi vedere, farmSelector è direttamente collegato a masterCtrl. E il comportamento di tale funzione loadFarmData è specifico per quel controller. In altre parole, farà solo cose che si applicano a quella pagina.

Il fatto è che questo farmSelector verrà utilizzato su altre pagine. E il comportamento preciso di un evento di cambiamento sarà diverso per ogni pagina. Quindi sto lottando per capire dove questo comportamento dovrebbe sedersi. E come sarebbe chiamato dipendente dal controller usando farmSelector.

L'articolo che ho collegato sopra suggerisce questo farmSelector dovrebbe essere in un servizio in modo che possa essere riutilizzato altrove. Ma sono ancora confuso su come potresti dare a un servizio generico un'azione specifica da intraprendere quando viene attivato un evento.

risposta

11

Consiglio vivamente anche un servizio, per lo stesso motivo suggerito dall'articolo. Ha anche un'ottima risposta al tuo problema.

Il termine tecnico per ciò che si desidera è una funzione calback. È, appunto, un'azione specifica da intraprendere quando viene attivato un evento e la sezione Servizi dell'articolo fornisce un buon esempio di come farlo.

Date un'occhiata a questa sezione dell'articolo servizi (che ho tagliato fino alle sezioni più importanti)

angular.module('myApp.services', []) 
    .factory('githubService', ['$http', function($http) { 

    var doRequest = function(username) { 
     return $http({ 
     url: 'https://MySuperURL.com/getTheData' 
     }); 
    } 

    return { 
     events: doRequest 
    }; 

}]); 

Quindi abbiamo un servizio ora, chiamato githubService, che ha un metodo: events (che in realtà è solo un nome diverso per doRequest;. ho mantenuto la ridenominazione in modo che fosse partita con il codice del articolo)

nascosto qui dietro le quinte è il $q API, che viene a volte indicato come il API 'promessa'. La funzione $http restituisce un oggetto 'promessa', che è in realtà solo un modo per il codice di tenere traccia di ciò che dovrebbe accadere quando viene eseguita la 'promessa'.Per esempio, diamo un'occhiata al prossimo codice (di nuovo, modificato dalla versione dell'articolo):

app.controller('ServiceController', ['$scope', 'githubService', 
function($scope, githubService) { 

    // uses the $http service to call the GitHub API 
    // and returns the resulting promise 
    githubService.events(newUsername) 
    .success(function(data, status, headers) { 
     // do magic stuff with the result 
     // (which is in the data param) 
     $scope.events = data.data; 
    }) 
}); 

}]);

Questo è dove sta accadendo la "magia". Guarda la chiamata a success(), e vedrai che in realtà stanno passando un function che dovrebbe essere eseguito quando la richiesta funziona. La funzione ha ancora accesso a tutte le variabili nel ServiceController a causa della chiusura, quindi è consentito utilizzare $scope e altre variabili. Tuttavia, è molto possibile scrivere un diverso metodo success() in ogni controller passando ogni volta una funzione diversa, che consente a più controllori di intraprendere azioni diverse. Al termine della richiesta, chiamerà ogni funzione success che è stata fornita.

È possibile seguire questo esempio di codice e ottenere un modello funzionante, ma suggerisco anche di dare un'occhiata a $q in angular e dare anche un'occhiata a questo articolo su callback functions. Devi capire entrambi per ottenere veramente quello che sta succedendo, ma la buona notizia è che entrambi sono usati abbastanza spesso in modo angolare, quindi valuterà il tuo tempo.

+0

Vorrei aver visto questa risposta prima di qualche ora di testa grattando come farlo. Grazie mille per lo sforzo –

Problemi correlati