ChatGPT解决这个技术问题 Extra ChatGPT

Update parent scope variable in AngularJS

I have two controllers, one wrapped within another. Now I know the child scope inherits properties from the parent scope but is there a way to update the parent scope variable? So far I have not come across any obvious solutions.

In my situation I have a calendar controller within a form. I would like to update the start and end dates from the parent scope (which is the form) so that the form has the start and end dates when submitted.

sounds like your calendar controller should be a directive.

C
Community

You need to use an object (not a primitive) in the parent scope and then you will be able to update it directly from the child scope

Parent:

app.controller('ctrlParent',function($scope){
    $scope.parentprimitive = "someprimitive";
    $scope.parentobj = {};
    $scope.parentobj.parentproperty = "someproperty";
});

Child:

app.controller('ctrlChild',function($scope){
    $scope.parentprimitive = "this will NOT modify the parent"; //new child scope variable
    $scope.parentobj.parentproperty = "this WILL modify the parent";
});

Working demo: http://jsfiddle.net/sh0ber/xxNxj/

See What are the nuances of scope prototypal / prototypical inheritance in AngularJS?


Thanks, this works! I should definitely read up on this (prototypical enheritance and primitives). Can you recommend a good read which explains a bit more than your SO link?
R
Ravbaker

There is one more way to do this task and to not use the $scope.$parent variable.

Just prepare a method for changing the value in parent scope and use it in child one. Like this:

app.controller('ctrlParent',function($scope) {
  $scope.simpleValue = 'x';
  $scope.changeSimpleValue = function(newVal) {
    $scope.simpleValue = newVal;
  };
});

app.controller('ctrlChild',function($scope){
    $scope.changeSimpleValue('y');
});

It also works and give you more control over the value changes.

You can then also call the method even in HTML like: <a ng-click="changeSimpleValue('y')" href="#">click me!</a>.


Good solution! this works because when something is not found in current $scope, Angular looks up in the $parent one. docs.angularjs.org/guide/scope (see 'Scope Hierarchies').
I like this answer, no need to create an unnecessary object.
Future readers: All of these high-five comments are a bit misguided. Creating two setter functions (which are "unnecessary objects") for every variable is a clunky and unnecessary kludge of inheritance and is not the Angular way. Misko Hevery, the creator of Angular, gives a talk in which he teaches "Whenever you have ng-model there’s gotta be a dot in there somewhere. If you don’t have a dot, you’re doing it wrong.” Misko video @ 29:19
how can I apply this solution by using controllerAS syntax?
D
DynamicNate

This also works (but not sure whether this follows best practice or not)

app.controller('ctrlParent',function($scope) {
    $scope.simpleValue = 'x';
});

app.controller('ctrlChild',function($scope){
    $scope.$parent.simpleValue = 'y';
});

You're correct, using $scope.$parent.value will work in most cases, however it's usually not the best idea to use extensively as it can get hard to manage in larger, more complicated projects.
r
rewritten

When you assign a primitive attribute to a scope, it is always local to the scope (possibly created on the fly), even if a parent scope has an attribute with the same name. This is a design decision, and a good one IMHO.

If you need to change some primitive (ints, booleans, strings) in the parent scope, from the view, you need it to be an attribute of another object in that scope, so the assignment may read:

<a ng-click="viewData.myAttr = 4">Click me!</a>

and it will, in turn:

get the viewData object from whatever scope it is defined in assign 4 to its myAttr attribute.


N
Nibu

For accessing variables declared in the parent, we should use $parent in child controller or template file

In controller

$scope.$parent.varaiable_name

In html template

ng-model="$parent.varaiable_name"