Reputation: 7424
I have a child controller that references values from it's parent.
The problem is: ng-repeat within the child controller view doesn't get updated when the parent controller values are updated.
So my question is: How does one update the child controller ng-repeat when parent controller values are updated while child values are by reference?
Child Controller:
angular.module('angularApp').controller('PostController', function ($scope)
{
$scope.mainController = $scope.$parent.getMainController();
$scope.editController = $scope.$parent;
$scope.posts = $scope.mainController.currentStation.posts;
$scope.featuredAlbums = $scope.$parent.featuredAlbums;
$scope.updatePost = function(postId){
$scope.editController.updatePost(postId);
};
$scope.updateFeatured = function(featuredId){
$scope.editController.updateFeatured(featuredId);
};
});
ng-repeat under the child controller
<div ng-controller="PostController" class="posts">
<div ng-repeat="featuredAlbum in featuredAlbums">
Example that breaks:
http://plnkr.co/edit/GKjYAWEEWOrp84bwIIOt?p=info
** Answer **
Thanks for the fast response guys, I realise that everything created within the controller is passed by value and not reference, even values referenced from parent controllers are recreated as locally scoped controller values.
So the solution? Simple.
Just call the parent directly instead of recreating locally scoped vars
$scope.$parent.$someValue
Upvotes: 0
Views: 579
Reputation: 1108
Imagine the scenario:
app.controller('ParentController', function($scope) {
$scope.rawValue = 3;
$scope.hiddenValue = false;
$scope.objectValue = {
name: 'David',
age: 27
};
$scope.someFunction = function(input) {
return input;
}
});
app.controller('ChildController', function($scope) {
$scope.hiddenValue = true;
//Notice i don't need to wrap calls to parent functions or reassign parent data.
//this is because the $scope object will automatically inherit from it's parent.
});
<div ng-controller="ParentController">
{{ hiddenValue }} //false, remains false as setting only occured on child scope;
{{ rawValue }} //3, remains 3 as setting will only occur on child scope;
{{ objectValue.name }} // 'David' however will dynamically update with input below.
<div ng-controller="ChildController">
{{ hiddenValue }} //true because now it's scoped;
<input type="button" ng-click="someFunction('hello')" value="calls function on parent scope" />
<input type="text" ng-model="rawValue" /> //will initialise as 3 but as soon as updated it will be scoped on this scope.
<input type="text" ng-model="objectValue.name" /> //will initialise as David and will correctly update parent scope as edited.
</div>
</div>
So why does this work?
Anytime you are accessing a property or function it will automatically travel up the $scope
hierarchy to find the value. No need to specify $parent
expressly as this is how javascript inheritance works.
However whenever you are modifying/setting a value it will occur on the nearest $scope
and be 'scoped'. that's what happens with hiddenValue
and rawValue
in example above. however notice that it works as expected on objectValue.name
this is because in order to set the name
property you must first 'get' objectValue
. therefore javascript inheritance travels up the scope chain to get objectValue
from the parent scope and then sets it's name
property.
Two guidelines:
Upvotes: 1
Reputation: 7736
What's happening is that you are getting a new copy of the data in the child scope and the parent scope is not updated.
The simplest way to make it work is not to store any objects that need to be accessible by child controllers directly on the parent scope. You will have less code and far fewer complications.
In your case, in the parent have something like:
$scope.media = {
featuredAlbums : [ ... ],
currentStation : {
posts : {...}
}
}
$scope.functions = {
updatePost : function (pid) {
// your function
},
updateFeatured : function (pid) {
// your function
}
}
and in the child don't bother with all the inheritance and just call functions directly :
$scope.functions.updatedFeatured(featureID);
$scope.functions.updatePost(postId);
it doesn't matter which parent controller your functions and data are in, it will find them if you attach to a property of the controller but not the controller itself.
Take a look at this video which explains it better.
https://egghead.io/lessons/angularjs-the-dot
EDIT
As David Beech points, there is no need to store parent scope functions in a property because the function is not being modified. However, this approach is meant to be a simple rule that will work without any extra thinking about which data/functions are read-only and which are writable.
Upvotes: 1
Reputation: 3823
I am not sure I understand your question correctly. So I created a plunker that included two controllers. It seems to me that child values are always updated. Can you show us how your original questions are related or not?
`http://plnkr.co/edit/9aHqdbbIe5aGJSuHogPA?p=preview`
Upvotes: 1