While attempting to answer a question regarding sharing data between two separate controllers I ran into a question .
I usually use services for for this task and began to create a jsfiddle, but I could not get it to work.
After a bit of debugging if I created the properties dynamically in setActivePersonWorks(person)
the dirty checking worked and the second controller showed the correct value.
If I assigned the value in setActivePersonDoesNotWork()
it did not.
If I used $timeout()
I was able to verify that DataService.badPerson
did indeed contain the correct data.
Am I doing something wrong? I guess if you do something with $apply()
it will work correctly, but why does creating the values dynamically cause things to just work?
Working Example:
var myTest = angular.module("MyTest", []);
myTest.factory("DataService", function () {
var People = {
goodPerson: {},
badPerson: {},
setActivePersonWorks: function (person) {
People.goodPerson.name = person.name;
People.goodPerson.id = person.id;
},
setActivePersonDoesNotWork: function (person) {
People.badPerson = person;
}
};
return People;
});
function ViewController($scope, DataService, $timeout) {
$timeout(function () {
DataService.setActivePersonWorks({
id: 1,
name: "Good Mark"
});
DataService.setActivePersonDoesNotWork({
id: 2,
name: "Bad Mark"
});
}, 1000);
}
function DetailController($scope, DataService, $timeout) {
$scope.goodPerson = DataService.goodPerson;
$scope.badPerson = DataService.badPerson;
$timeout(function(){
$scope.message = "DataService has the value: " + DataService.badPerson.name + " but $scope.badPerson is " + $scope.badPerson.name;
}, 2000);
}
The <html/>
<div ng-app="MyTest">
<div ng-controller="ViewController"></div>
<div ng-controller="DetailController">
<h1>Works: {{goodPerson.name}}</h1>
<h1>Does Not Work: {{badPerson.name}}</h1>
{{message}}
</div>
</div>
On jsfiddle
When Angular sees
<h1>Does Not Work: {{badPerson.name}}</h1>
it sets up a $watch on object badPerson
. Looking at your controller, $scope.badPerson
is a reference to object DataService.badPerson
. All is fine so far... the problem happens here:
setActivePersonDoesNotWork: function (person) {
People.badPerson = person;
}
When this function executes, badPerson
is assigned a new/different object reference, but the controller is still $watching the old/original object reference.
The fix is to use angular.copy() to update the existing badPerson
object, rather than assigning a new reference:
setActivePersonDoesNotWork: function (person) {
angular.copy(person, People.badPerson);
}
This also explains why setActivePersonWorks()
works -- it does not assign a new object reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With