在AngularJS中更新父范围变量


113

我有两个控制器,一个封装在另一个中。现在,我知道子范围从父范围继承属性,但是有没有办法更新父范围变量?到目前为止,我还没有遇到任何明显的解决方案。

在我的情况下,我在表单中有一个日历控制器。我想从父范围(即表单)更新开始日期和结束日期,以便表单在提交时具有开始日期和结束日期。


听起来您的日历控制器应该是指令。
约拿(Jonah)2013年

Answers:


192

您需要在父作用域中使用一个对象(不是原始对象),然后就可以直接从子作用域中更新它

上级:

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

儿童:

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";
});

工作演示http : //jsfiddle.net/sh0ber/xxNxj/

请参阅AngularJS中范围原型/原型继承的细微差别是什么?


1
当我尝试实现此错误时,出现此错误:“无法设置未定义的属性'parentproperty'。”
Malcr001

您可以发布代码吗?它正在小提琴演示中工作。如果您的日历控件使用隔离范围,则它将不会从父范围继承,因此您需要将值传递给指令的范围。

对不起,我忘记了这个问题。我接受了它,因为最终我确实设法在此答案的帮助下使其工作。
Malcr001 2013年

我知道将{{parentobj.parentproperty}}放在ctrlParent div元素中是声明parentobj对象并将该对象设置为ctrlParent范围的对象。这是正确的假设吗?
Stephane

1
谢谢,这有效!我绝对应该阅读一下(原型继承和基元)。您能推荐一本很好的读物,它比您的SO链接介绍更多的内容吗?
jvannistelrooy 2014年

116

还有另一种方法可以执行此任务并且不使用$scope.$parent变量。

只需准备一种方法来更改父范围中的值,然后在子范围中使用它。像这样:

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

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

它还可以使您对价值变化有更多的控制。

然后,您甚至还可以在HTML中调用该方法,例如:<a ng-click="changeSimpleValue('y')" href="#">click me!</a>


1
好的解决方案!之所以起作用,是因为当在当前$ scope中找不到某物时,Angular会在$ parent中查找。docs.angularjs.org/guide/scope(请参阅“范围层次结构”)。
Elo 2015年

我喜欢这个答案,无需创建不必要的对象。
grimmdude

3
未来的读者:所有这些前五条评论都被误导了。为每个变量创建两个setter函数(它们是“不必要的对象”)是一种笨拙且不必要的继承冲突,而不是Angular方式。Angular的创建者Misko Hevery在一次演讲中讲授“每当您有ng-model时,某处就会有一个点。如果您没有一个点,那就错了。” Misko视频 @ 29:19

如何使用controllerAS语法应用此解决方案?
niran

6

这也有效(但不确定是否遵循最佳实践)

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

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

1
没错,在大多数情况下,使用$ scope。$ parent.value可以使用,但是通常不建议广泛使用它,因为在大型,更复杂的项目中很难管理。
Alex Johnson

4

将原始属性分配给作用域时,它始终是合并范围时,即使父合并范围的属性具有相同的名称合并范围的本地(可能是动态创建的)。这是一项设计决定,也是不错的恕我直言。

如果您需要从视图中更改父作用域中的某些原语(int,布尔值,字符串),则需要将其作为该作用域中另一个对象的属性,因此赋值可能为:

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

然后,它将:

  1. 得到 viewData从定义的任何范围中对象
  2. 将4分配给它的myAttr属性。

4

要访问在父级中声明的变量,我们应该在子控制器或模板文件中使用$ parent

在控制器中

$scope.$parent.varaiable_name

在html模板中

ng-model="$parent.varaiable_name"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.