переменная $ 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 накапливается, как показано на скриншоте ниже. Я тоже не уверен, почему, если вы можете помочь объяснить и избежать этого.



Введите описание изображения здесь

554   1  

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) жизненный цикл controller является самым коротким в угловом мире. Он будет жить только во время государства. Как только мы покинем его, перейдите к другому - он исчезнет (если нет крючков утечки памяти)

2) область действия контроллера будет уничтожена, как только контроллер будет уничтожен... 3) мы должны думать о государствах как об изолированных островах. Если у нас есть доступ к состоянию $scope - даже во внутреннем объявление $rootScope.$on('$stateChangeSuccess' - у нас есть доступ к $ scope текущего состояния... текущего контроллера. Фактически, мы создаем кандидата на утечку памяти
app.controller('state1Ctrl', ...
  ...
  $rootScope.$on('$stateChangeSuccess', ...
     // HERE - $scope belongs to Controller, and its life cycle is very short
     $scope.data =
4) Если мы хотим изменить какое - то значение, inisde из "того же состояния" - после перехода мы должны переместить его. Он не может быть в текущем состоянии, потому что текущее состояние / представление / контроллер (и его область действия) не будут одинаковыми. 5) способ хранения данных - сервис (синглтон) или модель внутри родительского элемента (который будет наследоваться через вид / область наследования)

6) в $rootScope.$on должна быть объявлена в некоторых .метод run () - вне контроллера. Но в данном случае это, по-видимому, не добавляет никакой ценности. Потому что если мы поместим общие данные в какой-то сервис... мы можем сделать это в любом месте, например, в другом контроллере, а также

Comments

    Ничего не найдено.