95 votes

Exécution du code d'initialisation d'AngularJS lors du chargement de la vue

Lorsque je charge une vue, j'aimerais exécuter un code d'initialisation dans le contrôleur qui lui est associé.

Pour ce faire, j'ai utilisé la directive ng-init sur l'élément principal de ma vue :

<div ng-init="init()">
  blah
</div>

et dans le contrôleur :

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

    $scope.isSaving = false;
}

Première question : est-ce la bonne façon de procéder ?

Ensuite, j'ai un problème avec la séquence des événements qui se déroulent. Dans la vue, j'ai un bouton "Enregistrer", qui utilise l'attribut ng-disabled en tant que telle :

<button ng-click="save()" ng-disabled="isClean()">Save</button>

le site isClean() est définie dans le contrôleur :

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

Comme vous pouvez le voir, il utilise le $scope.isSaving qui a été initialisé dans le fichier init() fonction.

PROBLÈME : lorsque la vue est chargée, la fonction isClean est appelée. antes de le site init() d'où l'indicateur isSaving es undefined . Que puis-je faire pour éviter cela ?

138voto

Mark Rajcok Points 85912

Lorsque votre vue se charge, le contrôleur qui lui est associé se charge également. Au lieu d'utiliser ng-init il suffit d'appeler votre init() dans votre contrôleur :

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

Puisque votre contrôleur s'exécute avant ng-init ce qui résout également votre deuxième problème.

Violon


Comme John David Five mentionné, vous pourriez ne pas vouloir attacher ceci à $scope afin de rendre cette méthode privée.

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

Voir jsFiddle


Si vous voulez attendre que certaines données soient prédéfinies, déplacez cette demande de données vers une résolution ou ajoutez un watcher à cette collection ou à cet objet et appelez votre méthode init lorsque vos données répondent à vos critères init. En général, je supprime l'observateur une fois que mes exigences en matière de données sont satisfaites, de sorte que la fonction init ne se ré-exécute pas de manière aléatoire si les données que vous observez changent et répondent à vos critères pour exécuter votre méthode init.

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

39voto

lin Points 13836

Depuis AngularJS 1.5, nous devons utiliser $onInit qui est disponible sur tout composant AngularJS. Tiré du documentation sur le cycle de vie des composants depuis la v1.5, c'est la méthode préférée :

$onInit() - Appelé sur chaque contrôleur après que tous les contrôleurs d'une application élément ont été construits et que leurs liens ont été initialisés (et avant les fonctions de pré et post liaison pour les directives sur cet élément). élément). C'est un bon endroit pour placer le code d'initialisation de votre contrôleur. contrôleur.

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';
    }
});

Démonstration de violon

Un exemple avancé d'utilisation du cycle de vie des composants :

Le cycle de vie des composants nous donne la possibilité de gérer les composants d'une bonne manière. Il nous permet de créer des événements pour, par exemple, "init", "change" ou "destroy" d'un composant. De cette façon, nous sommes en mesure de gérer les éléments qui dépendent du cycle de vie d'un composant. Ce petit exemple montre comment enregistrer et désenregistrer un composant $rootScope écouteur d'événements $on . En sachant, qu'un événement $on limite sur $rootScope ne sera pas déconnecté lorsque le contrôleur perd sa référence dans la vue ou lorsqu'il est détruit. $rootScope.$on l'auditeur manuellement.

Un bon endroit pour mettre ces trucs est $onDestroy fonction du cycle de vie d'un composant :

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();
  }
});

Démonstration de violon

17voto

Joseph Oster Points 1089

Ou vous pouvez simplement initialiser en ligne dans le contrôleur. Si vous utilisez une fonction d'initialisation interne au contrôleur, elle n'a pas besoin d'être définie dans la portée. En fait, elle peut être auto-exécutée :

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 }
}

14voto

1101 Points 454

J'utilise le modèle suivant dans mes projets :

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  */ {
            // ...
        }

    });

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X