Esecuzione del codice di inizializzazione AngularJS al caricamento della vista

Quando carico una vista, vorrei eseguire un codice di inizializzazione nel controller associato.

Per fare ciò, ho usato la direttiva ng-init sull’elemento principale della mia vista:

blah

e nel controller:

 $scope.init = function () { if ($routeParams.Id) { //get an existing object }); } else { //create a new object } $scope.isSaving = false; } 

Prima domanda: è questo il modo giusto per farlo?

La prossima cosa, ho un problema con la sequenza di eventi che si svolgono. Nella vista ho un pulsante ‘salva’, che usa la direttiva ng-disabled quanto tale:

  

la funzione isClean() è definita nel controller:

 $scope.isClean = function () { return $scope.hasChanges() && !$scope.isSaving; } 

Come puoi vedere, usa il flag $scope.isSaving , che è stato inizializzato nella funzione init() .

PROBLEMA: quando la vista viene caricata, la funzione isClean viene chiamata prima della funzione init() , quindi il flag isSaving undefined è undefined . Cosa posso fare per impedirlo?

Quando viene caricata la vista, lo stesso vale per il controller associato. Invece di usare ng-init , chiama semplicemente il tuo metodo init() nel tuo controller:

 $scope.init = function () { if ($routeParams.Id) { //get an existing object } else { //create a new object } $scope.isSaving = false; } ... $scope.init(); 

Poiché il tuo controller gira prima di ng-init , questo risolve anche il tuo secondo problema.

Violino


Come menzionato da John David Five , potresti non voler albind questo a $scope per rendere questo metodo privato.

 var init = function () { // do something } ... init(); 

Vedi jsFiddle


Se si desidera attendere la preselezione di determinati dati, spostare la richiesta di dati in una risoluzione o aggiungere un watcher alla raccolta o all’object e chiamare il metodo init quando i dati soddisfano i criteri di init. Solitamente rimuovo l’osservatore una volta soddisfatti i miei requisiti di dati, quindi la funzione init non viene eseguita di nuovo in modo casuale se i dati osservati cambiano e soddisfano i criteri per eseguire il metodo init.

 var init = function () { // do something } ... var unwatch = scope.$watch('myCollecitonOrObject', function(newVal, oldVal){ if( newVal && newVal.length > 0) { unwatch(); init(); } }); 

Dal momento che AngularJS 1.5 dovremmo usare $onInit che è disponibile su qualsiasi componente di AngularJS. Tratto dalla documentazione del ciclo di vita dei componenti a partire dalla v1.5 è il modo preferito:

$ onInit () – Chiamato su ciascun controller dopo che tutti i controller su un elemento sono stati costruiti e hanno inizializzato i loro binding (e prima delle funzioni di collegamento pre e post per le direttive su questo elemento). Questo è un buon posto dove mettere il codice di inizializzazione per il tuo controller.

 var myApp = angular.module('myApp',[]); myApp.controller('MyCtrl', function ($scope) { //default state $scope.name = ''; //all your init controller goodness in here this.$onInit = function () { $scope.name = 'Superhero'; } }); 

>> Demo di Fiddle


Un esempio avanzato di utilizzo del ciclo di vita dei componenti:

Il ciclo di vita dei componenti ci dà la possibilità di gestire i componenti in un buon modo. Ci consente di creare eventi per es. “Init”, “change” o “destroy” di un componente. In questo modo siamo in grado di gestire cose che dipendono dal ciclo di vita di un componente. Questo piccolo esempio mostra come registrare e $rootScope registrazione di un $rootScope $on . Sapendo che un evento $on $rootScope su $rootScope non verrà annullato quando il controller perde il suo riferimento nella vista o viene distrutto, è necessario distruggere un $rootScope.$on listener manualmente. Un buon posto per mettere quella roba è $onDestroy funzione del ciclo di vita di un componente:

 var myApp = angular.module('myApp',[]); myApp.controller('MyCtrl', function ($scope, $rootScope) { var registerScope = null; this.$onInit = function () { //register rootScope event registerScope = $rootScope.$on('someEvent', function(event) { console.log("fired"); }); } this.$onDestroy = function () { //unregister rootScope event by calling the return function registerScope(); } }); 

>> Demo di Fiddle

O puoi semplicemente inizializzare in linea nel controller. Se si utilizza una funzione init interna al controller, non è necessario definirla nell’ambito. In effetti, può essere autoattuato:

 function MyCtrl($scope) { $scope.isSaving = false; (function() { // init if (true) { // $routeParams.Id) { //get an existing object } else { //create a new object } })() $scope.isClean = function () { return $scope.hasChanges() && !$scope.isSaving; } $scope.hasChanges = function() { return false } } 

Io uso il seguente modello nei miei progetti:

 angular.module("AppName.moduleName", []) /** * @ngdoc controller * @name AppName.moduleName:ControllerNameController * @description Describe what the controller is responsible for. **/ .controller("ControllerNameController", function (dependencies) { /* type */ $scope.modelName = null; /* type */ $scope.modelName.modelProperty1 = null; /* type */ $scope.modelName.modelPropertyX = null; /* type */ var privateVariable1 = null; /* type */ var privateVariableX = null; (function init() { // load data, init scope, etc. })(); $scope.modelName.publicFunction1 = function () /* -> type */ { // ... }; $scope.modelName.publicFunctionX = function () /* -> type */ { // ... }; function privateFunction1() /* -> type */ { // ... } function privateFunctionX() /* -> type */ { // ... } });