Когда я загружаю представление, я хочу запустить некоторый код инициализации в связанном с ним контроллере.
Для этого я использовал директиву ng-init в основном элементе моего представления:
<div ng-init="init()">
blah
</div>
и в контроллере:
$scope.init = function () {
if ($routeParams.Id) {
//get an existing object
});
} else {
//create a new object
}
$scope.isSaving = false;
}
Первый вопрос: правильно ли это делать?
Следующее, у меня проблема с последовательностью происходящих событий. В представлении у меня есть кнопка «сохранить», которая использует ng-disabled
директиву как таковую:
<button ng-click="save()" ng-disabled="isClean()">Save</button>
isClean()
функция определена в контроллере:
$scope.isClean = function () {
return $scope.hasChanges() && !$scope.isSaving;
}
Как видите, он использует $scope.isSaving
флаг, который был инициализирован в init()
функции.
ПРОБЛЕМА: когда вид загружен, isClean функция вызывается перед тем в init()
функции, следовательно , флаг isSaving
является undefined
. Что я могу сделать, чтобы это предотвратить?
Начиная с AngularJS 1.5, мы должны использовать то,
$onInit
что доступно в любом компоненте AngularJS. Взято из документации по жизненному циклу компонента, начиная с версии 1.5, это предпочтительный способ: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'; } });
>> Демо скрипки
Продвинутый пример использования жизненного цикла компонента:
Жизненный цикл компонента дает нам возможность правильно обрабатывать компоненты. Это позволяет нам создавать события, например, для «инициализации», «изменения» или «уничтожения» компонента. Таким образом, мы можем управлять вещами, которые зависят от жизненного цикла компонента. Этот небольшой пример показывает, как зарегистрировать и отменить регистрацию
$rootScope
прослушивателя событий$on
. Зная, что событие$on
переплетено на$rootScope
не будет undinded , когда контроллер теряет свою ссылку в окне или получить уничтожено , мы должны уничтожить$rootScope.$on
слушатель вручную. Хорошее место для этого -$onDestroy
функция жизненного цикла компонента: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(); } });
>> Демо скрипки
источник
Или вы можете просто инициализировать встроенный в контроллер. Если вы используете внутреннюю для контроллера функцию инициализации, ее не нужно определять в области. Фактически, это может быть самовыполняющийся:
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 } }
источник
В своих проектах я использую следующий шаблон:
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 */ { // ... } });
источник