javascript - $scope variable not update within $rootScope.$on -
this show number 1
, change button. when click button, supposed trigger $state.go , within controller, should detect event in $rootscope.$on
, update number 2
. however, reason cannot number (data.id
) update using $digest or $apply.
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>
state1.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); }); }); });
can find mistake on why data.id
did not update in view?
update 1
from radim response below, changed code bit better reflect real code: http://plnkr.co/edit/yyg0hrl5igzp4e44aret?p=preview
basic didn't have situation parent state in case. want same state, trigger state new params , change $scope variable objects. that's all.
js
var = 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); }); });
i found out after clicking change 4 times, number of $statechangesuccess
event piling screenshot below. not sure why either if can explain , avoid this.
the reason is, recreating data
every time
// create new reference data // in current scope, while not effecting other (parent) $scope.data = {id: 2};
if want update existing reference have
// here work existing reference // if created, used, id property updated $scope.data = $scope.data || {}; $scope.data.id = 2;
there an updated version.
the state has parent, $scope inheriting time, can use shared holder $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' });
the controller updated def:
app.controller('state1ctrl', function ($scope, $rootscope, $state, $stateparams) { // no $scope.data definition, used inherited //$scope.data = {id: 3}; $rootscope.$on('$statechangesuccess', function(evt, tostate, toparams, fromstate, fromparams) { console.log($scope.data); // because state change listener still have access $scope // can update value of data.id // because in fact parent reference // se next state have access //$scope.$apply(function() { $scope.data = $scope.data || {}; $scope.data.id = toparams.id; console.log($scope.data); //}); }); });
and parent controller, reference data definition
app.controller('state1parentctrl', function ($scope, $rootscope, $state, $stateparams) { $scope.data = { id : 1 }; })
check here.
i not saying way should go. trying show issue, , how solved
extend: without parent state?
from extended question:
basic didn't have situation parent state in case. want same state, trigger that state new params , change $scope variable objects. that's all.
so, issues here.
1) controller
lifecycle shortest, in angular world. live during state. once leave it, navigate other - disappear (if no memory leak hooks in place)
2) controller's scope destroyed, once controller destroyed...
3) have think states isolated islands. if have access state $scope
- in internal declaration $rootscope.$on('$statechangesuccess'
- have access $scope of current state... of current controller. in fact, create candidate memory leak
app.controller('state1ctrl', ... ... $rootscope.$on('$statechangesuccess', ... // here - $scope belongs controller, , life cycle short $scope.data =
4) if want change value, inisde of "same state" - after transition have move out. cannot in current state, because current state/view/controller (and it's scope) not same.
5) way how keep data - service (singleton) or model inside of parent (which inherited through view/scope inheritance)
6) $rootscope.$on
should declared in .run() method - outside of controller. in case, not seem adding value. because if place shared data service... can anyhwere, e.g. in other controller
Comments
Post a Comment