переменная $ scope не обновляется в пределах $rootScope.$на
Это показать номер 1 и кнопкуизменить . Когда я нажимаю эту кнопку, она должна вызвать $state.идите и внутри контроллера, он должен обнаружить событие в $rootScope.$on и обновить число до 2. Однако по какой-то причине я не могу получить номер (data.id) для обновления даже с помощью $digest или $применять.
Http://plnkr.co/edit/3qHnIm?p=preview
HTML
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<script data-require="angular.js@*" data-semver="1.4.0-beta.5" src="https://code.angularjs.org/1.4.0-beta.5/angular.js"></script>
<script data-require="ui-router@*" data-semver="0.2.13" src="//rawgit.com/angular-ui/ui-router/0.2.13/release/angular-ui-router.js"></script>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title></title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />
</head>
<body class="container">
<div ui-view=""></div>
<div ng-controller="state2Ctrl">
<a href="#" ng-click="change()">Change</a>
</div>
<script src="app.js"></script>
<script src="controllers.js"></script>
</body>
</html>
Состояние 1.html
<p>{{ data.id }}</p>
JS
var app = angular.module('myapp', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/state1/0');
$stateProvider
.state('state1', {
url: '/state1/:id',
controller: 'state1Ctrl',
templateUrl: 'state1.html'
});
});
app.controller('state2Ctrl', function ($scope, $rootScope, $state, $stateParams) {
$scope.i = 1;
$scope.change = function(){
console.log('change state1');
$state.go('state1', {id: $scope.i++});
};
});
app.controller('state1Ctrl', function ($scope, $rootScope, $state, $stateParams) {
$scope.data = {id: 1};
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
console.log($scope.data);
$scope.$apply(function() {
$scope.data = {id: 2};
console.log($scope.data);
});
});
});
Может кто-нибудь найти мою ошибку о том, почему data.id не получил обновление в представлении?
Обновление 1
Из ответа Radim ниже я немного изменил код, чтобы лучше отразить мой реальный код: http://plnkr.co/edit/yyg0Hrl5IgzP4e44aRet?p=preview
Основной я не делал есть ситуация с родительским государством в моем случае. То, что я хочу сделать, это из того же состояния, вызвать это состояние с новыми парами и изменить некоторые объекты переменной $ scope. Это все.
JS
var i = 1;
app.controller('state1Ctrl', function($scope, $rootScope, $state, $stateParams) {
$scope.change = function() {
console.log('change state1: ' + i);
$state.go('state1', {
id: i++
});
};
$scope.data = {
id: 1
};
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
console.log('$stateChangeSuccess: ');
console.log($scope.data);
$scope.data = $scope.data || {};
$scope.data.id = toParams.id;
console.log('After assign:');
console.log($scope.data);
});
});
Я узнал, нажав Изменить 4 раза, количество событий $stateChangeSuccess накапливается, как показано на скриншоте ниже. Я тоже не уверен, почему, если вы можете помочь объяснить и избежать этого.

1 ответ:
Причина в том, что вы воссоздаете
dataкаждый раз// this will create new reference to data // in current scope, while not effecting any other (parent) $scope.data = {id: 2};Если вы хотите обновить существующую ссылку, мы должны это сделать
// here we work with existing reference // if it was created, it will be used, the id property will be updated $scope.data = $scope.data || {}; $scope.data.id = 2;Существует обновленная версия.
Теперь у государства есть родитель, который $scope мы будем наследовать все время, поэтому мы можем использовать его в качестве общего держателя для
$scope.data$stateProvider .state('state1Parent', { template: '<div ui-view=""></div>', controller: 'state1ParentCtrl', }); $stateProvider .state('state1', { parent: 'state1Parent', url: '/state1/:id', controller: 'state1Ctrl', templateUrl: 'state1.html' });Контроллер обновил def:
app.controller('state1Ctrl', function ($scope, $rootScope, $state, $stateParams) { // no $scope.data definition, used the inherited //$scope.data = {id: 3}; $rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) { console.log($scope.data); // because this state change listener still have access to $scope // we can update the value of data.id // because it is in fact parent reference // se even next state will have access to it //$scope.$apply(function() { $scope.data = $scope.data || {}; $scope.data.id = toParams.id; console.log($scope.data); //}); }); });И родительский контроллер с определением справочных данных
app.controller('state1ParentCtrl', function ($scope, $rootScope, $state, $stateParams) { $scope.data = { id : 1 }; })Проверьте это здесь .
Я не говорю, что мы должны идти этим путем. Но пытаясь показать, в чем заключается проблема, и как ее можно решитьEXTEND: можем ли мы сделать это без родительского состояния?
Из расширенного вопроса:
Basic Iне было ситуации сродительским состоянием в моем случае. То, что я хочу сделать, это из того же состояния, вызвать это состояние с новыми парами и изменить некоторую переменную $scope объекты. Это все.
Итак, каковы здесь проблемы.
1) жизненный цикл
2) область действия контроллера будет уничтожена, как только контроллер будет уничтожен... 3) мы должны думать о государствах как об изолированных островах. Если у нас есть доступ к состояниюcontrollerявляется самым коротким в угловом мире. Он будет жить только во время государства. Как только мы покинем его, перейдите к другому - он исчезнет (если нет крючков утечки памяти)$scope- даже во внутреннем объявление$rootScope.$on('$stateChangeSuccess'- у нас есть доступ к $ scope текущего состояния... текущего контроллера. Фактически, мы создаем кандидата на утечку памяти4) Если мы хотим изменить какое - то значение, inisde из "того же состояния" - после перехода мы должны переместить его. Он не может быть в текущем состоянии, потому что текущее состояние / представление / контроллер (и его область действия) не будут одинаковыми. 5) способ хранения данных - сервис (синглтон) или модель внутри родительского элемента (который будет наследоваться через вид / область наследования)app.controller('state1Ctrl', ... ... $rootScope.$on('$stateChangeSuccess', ... // HERE - $scope belongs to Controller, and its life cycle is very short $scope.data =6) в
$rootScope.$onдолжна быть объявлена в некоторых .метод run () - вне контроллера. Но в данном случае это, по-видимому, не добавляет никакой ценности. Потому что если мы поместим общие данные в какой-то сервис... мы можем сделать это в любом месте, например, в другом контроллере, а также
Comments