Reputation: 12034
I want to watch the myApp.myUser
changes:
<html ng-app="myApp">
<head>
<script src="js/vendor/angular/angular.min.js"></script>
<script src="js/app2.js"></script>
</head>
<body>
<div id="users" ng-controller="usersController">
<h4>usersController</h4>
test = {{myUser}}
</div>
<div id="tasks" ng-controller="tasksController">
<button ng-click="clickMe()">cliquez ici </button>
</div>
</body>
</html>
and app2.js:
var myApp = angular.module('myApp', []);
myApp.users = {};
myApp.tasks = {};
myApp.myUser = {id:1, username:'john'}
myApp.controller('usersController', function($scope) {
$scope.myUser = myApp.myUser;
$scope.$watch(myApp.myUser, $scope.userChanged);
$scope.userChanged = function() {
console.log('userChanged');
}
});
myApp.controller('tasksController', function($scope) {
$scope.tasks = myApp.tasks;
$scope.clickMe = function() {
myApp.myUser = {id:2, username:'jack'}
}
});
I tried that with console:
myApp.myUser = {id:2, username:'jack'}
Nothing.
Then I tried to pass that through the AngularJS with tasksController
$scope.clickMe = function() {
myApp.myUser = {id:2, username:'jack'}
}
Nothing changes on my view!
http://jsfiddle.net/halirgb/Lvc0u55v/
Upvotes: 2
Views: 4159
Reputation: 581
Don't use properties on your myApp
variable, that literally holds all of the AngularJS functionality, and you risk collisions.
You have a couple options for storing data in AngularJS:
$rootScope
- Operates just like $scope
, but is attached to the whole app, not just the current controller.That would look something like...
myApp.factory('dataService', function() {
// this is simplified for illustration, see edit below
return {
myUser: {id: 1, username: 'john'},
};
});
myApp.controller('usersController', function($scope, dataService) {
$scope.myUser = dataService.myUser;
});
EDIT:
As discussed in comments, this brings up another potential binding issue, since I used a literal value that can be overwritten via userService.myUser = {};
. A better data service, which would provide more reliable 2-way binding, would look like:
myApp.factory('dataService', function() {
var users = [
{ id: 1, username: 'john' }
];
return {
getUser: function(id) {
for (i=0; i<users.length; i++) {
if (users[i].id === id) {
return users[i];
}
}
}
};
});
myApp.controller('usersController', function($scope, dataService) {
$scope.myUser = dataService.getUser(1);
});
Upvotes: 2
Reputation: 41543
I would suggest you to use the variables by declaring it in a service as
var myApp = angular.module('myApp', []);
myApp.factory('DataService',function(){
var myUser ={id:1, username:'john'};
var tasks;
var users;
return{
users:users,
tasks:tasks,
myUser:myUser
}
});
myApp.controller('usersController', function($scope,DataService) {
$scope.myUser = DataService.myUser;
console.log(DataService.myUser);
$scope.$watch(DataService.myUser, $scope.userChanged);
$scope.userChanged = function() {
console.log('userChanged');
}
});
myApp.controller('tasksController', function($scope,DataService) {
$scope.tasks = DataService.tasks;
$scope.clickMe = function() {
DataService.myUser = {id:2, username:'jack'}
}
});
Upvotes: 2
Reputation: 828
As shown in the docs for $scope.$watch, the first argument must be a watchExpression
- that is, an Angular expression (a string
) describing what value in $scope
should be watched.
Your value myApp.myUser
is not part of $scope
and cannot be reached by $watch
. The solution would be to move your object into something like $scope.myUser
and then call $scope.$watch('myUser', function() { console.log('userChanged'); });
.
Be warned that:
$watch
can be expensive if you set up a lot of watches. You usually want a watch set up for data that your users can manipulate on the view, but not for data that you're directly loading through code.$watch
will only track changes to the reference, so $scope.myUser = {};
would trigger a listener callback but $scope.myUser.username = 'jack';
would not. You can pass a third argument true
to make it check for deep inequality, but this gets even more expensive with complex objects or lots of watches.Upvotes: 1