Angular JS如何将子作用域变量的更改传递到父作用域?

47
如何将变量更改传递回ParentCtrl,即使在ChildCtrl中实例化了一个新的变量?额外的分数是尽可能少地使用$on和$watch(这样更容易实现)
ParentCtrl
- ChildCtrl / ChildCtrl2 / ChildCtrl3 / ChildCtrl4 - View
我的ChildCtrl有足够不同,无法轻松抽象出主布局和ng-view,但它们都依赖于ParentCtrl中的相同函数。 $scope.searchTerms在ParentCtrl中定义,但具有ng-model ='searchTerms'的输入框位于子控制器的视图中。当此变量更改时,仅在ChildCtrls中反映,而不在ParentCtrl中。

Example: http://jsfiddle.net/JHwxP/22/

HTML部分

<div ng-app>
    <div ng-controller="Parent">
        parentX = {{x}} <br/>
        parentY = {{y}}<br/>
        <div ng-controller="Child">
            childX = {{x}}<br/>
            childY = {{y}}<br/>
            <a ng-click="modifyBothScopes()">modifyBothScopes</a><br>
            <br>
            The changes here need to appear in 'Parent'. <input ng-model='y'>
        </div>
    </div>
</div>

控制器

function Parent($scope) {
    $scope.x= 5;
    $scope.y= 5;
}

function Child($scope) {
    $scope.modifyBothScopes= function() {
       $scope.$parent.x++;
    };  
}

更新

我目前正在尝试使用共享服务方法:https://gist.github.com/exclsr/3595424

更新

尝试使用发射/广播系统

已解决 问题: 我在父级中存储了 $scope.searchTerms,当更改时在子级 $scope 中创建了一个空格。

解决方案: 我应该在父级中使用 $scope.search.terms,并在子级中更改它,这样它就会向上冒泡到父级。

示例:http://jsfiddle.net/JHwxP/23/

3个回答

88

这是因为原型继承的工作方式。

当你在子控制器中请求$scope.x时,它会检查它的作用域中是否定义了x,如果没有,则在父作用域中查找x。

如果你将值分配给子作用域的x属性,它只会修改子作用域。

处理这个问题并获得共享行为的简单方法是使用对象或数组。

function ParentCtrl($scope) {
  $scope.model = {x: 5, y: 5};
}

function ChildCtrl($scope) {
  $scope.update = function(x, y) {
    $scope.model.x = x;
    $scope.model.y = y;
  };
}

在这里,更改将在两个范围中都可见,因为$scope.model将在父范围和子范围中引用相同的对象。

John Lindquist有一个关于这个主题的视频


9
我知道Misko说过“如果你没有使用点,那么你就做错了什么事情。”但我从未亲身体验过。以下是一个可行的示例:http://jsfiddle.net/JHwxP/23/ - Michael J. Calkins

15

另一种不需要创建大量对象来传递引用的解决方案是在父控制器中创建设置器函数。

function ParentCtrl($scope) {
  $scope.x = 5;
  $scope.y = 5;

  $scope.setX = function(value) {
    $scope.x = value;
  }

  $scope.setY = function(value) {
    $scope.y = value;
  }
}

function ChildCtrl($scope) {
  $scope.update = function(x, y) {
    $scope.setX(x);
    $scope.setY(y);
  };
}

当数据不应该成为同一对象的一部分时,我认为这样做更加清晰。

你还可以在子对象中尝试类似这样的事情:

function ChildCtrl($scope) {
  var superSetX = $scope.setX;
  $scope.setX = function(value) {
    superSetX(value * 2);
  };
  ...
}

1
我在寻找类似的东西。第一个解决方案是在阅读this之后出现的。您可以与子控制器共享父模型。 这里有一个例子。我甚至使用了一组项目来证明我的观点。像它们都是同一个宇宙的一部分一样,ChildController正在改变他的父级。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接