I have a fairly large Angular app with 15 directives and 5 services. The problem I'm having is related to updating the local scope from within a service. And with updating I mean replacing the array the scope is pointing at to another array.
The process is the following after I click an element:
clickDirective () {
restrict: 'A'.
link: function (scope, element, attrs) {
if ($rootScope.hasCertainValue) {
FirstService.handle(scope, valueX)
}
}
}
/* Calls FirstService.handle */
FirstService () {
handle (scope, valueX) {
if (certainCriteriaMet) {
SecondService.handle(scope, valueX)
}
}
}
/* Calls SecondService.handle */
SecondService () {
handle (scope, valueX) {
/* This is the funny part*/
console.log(scope.value) // let's assume prints: ['a']
// Option a)
scope.value = ['a', 'b'] // this is what I want to do
// Option b)
scope.value.push('b') // this is what works
scope.$apply()
// Now if we ran option a) the UI is not updated
console.log(scope.value) // prints ['a', 'b'] however
// But when this function is called the next time
// the value of scope.value has switched back to ['a'].
// If we ran option b) instead, the UI is updated
console.log(scope.value) // prints ['a', 'b'] as expected
// The difference is that the value of scope.value is
// still ['a', 'b'] the next time this function is called.
}
}
So the question here is that why can't I change the object the scope is pointing at? But I can modify it instead?
The SecondService contains another function called by another directive, using the same scope. And in that function I can perform the operation I want - which is replacing the current array with a new one.
The only reasons I can think of are some sort of race conditions.
----- Edit -----
I think I'm starting to catch the problem here. The scope object I have in the SecondService is only a pointer to the real scope object.
scope.value ------> [array]
scope.atSecondService --------> scope.value -------> [array]
So when I change the array at scope.atSecondService this is what I get:
scope.value ------> [array]
scope.atSecondService -----> [newArray] <---/--- scope.value
This still makes me wonder, though, that why can I call a similar function from another directive where this works?
----- Edit 2 -----
Or maybe I'm wrong. The behavior is not consistent. It seems like I get a new local level scope created at the element level instead of accessing the $scope at the controller. However, the first time I receive the scope it's the controller's scope - that's confirmed from its value.
Maybe someone else knows better?