AngularJS从子控制器访问父作用域


382

我已经使用设置了我的控制器 data-ng-controller="xyzController as vm"

我有一个父/子嵌套控制器的场景。通过使用$parent.vm.property,我可以毫无问题地访问嵌套html中的父属性,但是我无法弄清楚如何从子控制器中访问父属性。

我试过注入$ scope然后使用$scope.$parent.vm.property,但这不起作用吗?

谁能提供建议?

Answers:


620

如果您的HTML如下所示,则可以执行以下操作:

<div ng-controller="ParentCtrl">
    <div ng-controller="ChildCtrl">
    </div>
</div>

然后您可以按如下方式访问父范围

function ParentCtrl($scope) {
    $scope.cities = ["NY", "Amsterdam", "Barcelona"];
}

function ChildCtrl($scope) {
    $scope.parentcities = $scope.$parent.cities;
}

如果要从视图访问父控制器,则必须执行以下操作:

<div ng-controller="xyzController as vm">
   {{$parent.property}}
</div>

参见jsFiddle:http : //jsfiddle.net/2r728/

更新资料

实际上,由于您cities是在父控制器中定义的,因此子控制器将继承所有作用域变量。因此从理论上讲,您不必致电$parent。上面的示例也可以编写如下:

function ParentCtrl($scope) {
    $scope.cities = ["NY","Amsterdam","Barcelona"];
}

function ChildCtrl($scope) {
    $scope.parentCities = $scope.cities;
}

AngularJS文档使用这种方法,您可以在此处阅读有关的更多信息$scope

另一个更新

我认为这是对原始海报的更好回答。

的HTML

<div ng-app ng-controller="ParentCtrl as pc">
    <div ng-controller="ChildCtrl as cc">
        <pre>{{cc.parentCities | json}}</pre>
        <pre>{{pc.cities | json}}</pre>
    </div>
</div>

JS

function ParentCtrl() {
    var vm = this;
    vm.cities = ["NY", "Amsterdam", "Barcelona"];
}

function ChildCtrl() {
    var vm = this;
    ParentCtrl.apply(vm, arguments); // Inherit parent control

    vm.parentCities = vm.cities;
}

如果使用该controller as方法,则还可以按以下方式访问父范围

function ChildCtrl($scope) {
    var vm = this;
    vm.parentCities = $scope.pc.cities; // note pc is a reference to the "ParentCtrl as pc"
}

如您所见,有许多不同的访问方式$scopes

更新小提琴

function ParentCtrl() {
    var vm = this;
    vm.cities = ["NY", "Amsterdam", "Barcelona"];
}
    
function ChildCtrl($scope) {
    var vm = this;
    ParentCtrl.apply(vm, arguments);
    
    vm.parentCitiesByScope = $scope.pc.cities;
    vm.parentCities = vm.cities;
}
    
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script>
<div ng-app ng-controller="ParentCtrl as pc">
  <div ng-controller="ChildCtrl as cc">
    <pre>{{cc.parentCities | json}}</pre>
    <pre>{{cc.parentCitiesByScope | json }}</pre>
    <pre>{{pc.cities | json}}</pre>
  </div>
</div>


6
我认为最近一次更新的两个问题是:1.继承父范围可能会导致潜在的名称空间冲突,并且2.需要知道父控制器别名为“ pc”。这使得重用更加困难。
tchen 2014年

2
您将控制器定义为函数CtrlName(...){},但是如何使用Angular命名法实现呢?例如:angular.module(MdlName).controller(CtrlName,function(...){});
Pedro Justo 2014年

1
你什么意思?控制器只是功能吗?即angular.module('app').controller('ParentCtrl', ParentCtrl);
Dieterg 2014年

1
对不起,你说得对!在“控制器为”方法中,使用“ $ scope.pc.cities;”。在我看来,访问父城市是一个“后退”,因为如果在childCtrl中我们没有属性“ cities”,它将自动访问父城市。有没有其他办法可以解决这个问题?
Pedro Justo 2014年


46

我刚检查

$scope.$parent.someProperty

为我工作。

它将是

{{$parent.someProperty}}

为视图。


嗯,不为我工作。想知道它是否与控制器作为vm语法有关。
zpydee 2014年

如果您已命名父控制器,则可以将$ parent放入模板中,并使用{{vm.someProperty}}
solbs

8

当您使用as语法(如 ParentController as parentCtrl)来定义控制器,然后在子控制器中访问父范围变量时,请使用以下命令:

var id = $scope.parentCtrl.id;

where parentCtrl是使用as语法的父控制器的名称,并且id是在同一控制器中定义的变量。


2

有时您可能需要直接在子范围内更新父属性。例如,在子控制器更改之后,需要保存父控件的日期和时间。例如JSFiddle中的代码

的HTML

<div ng-app>
<div ng-controller="Parent">
    event.date = {{event.date}} <br/>
    event.time = {{event.time}} <br/>
    <div ng-controller="Child">
        event.date = {{event.date}}<br/>
        event.time = {{event.time}}<br/>
        <br>
        event.date: <input ng-model='event.date'><br>
        event.time: <input ng-model='event.time'><br>
    </div>
</div>

JS

    function Parent($scope) {
       $scope.event = {
        date: '2014/01/1',
        time: '10:01 AM'
       }
    }

    function Child($scope) {

    }

1

您还可以规避范围继承,并将事物存储在“全局”范围中。

如果您的应用程序中有一个主控制器包装了所有其他控制器,则可以在全局范围内安装一个“钩子”:

function RootCtrl($scope) {
    $scope.root = $scope;
}

然后,在任何子控制器中,您都可以使用来访问“全局”作用域$scope.root。您在此处设置的任何内容都将全局可见。

例:

function RootCtrl($scope) {
  $scope.root = $scope;
}

function ChildCtrl($scope) {
  $scope.setValue = function() {
    $scope.root.someGlobalVar = 'someVal';
  }
}

function OtherChildCtrl($scope) {
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app ng-controller="RootCtrl">
  
  <p ng-controller="ChildCtrl">
    <button ng-click="setValue()">Set someGlobalVar</button>
  </p>
  
  <p ng-controller="OtherChildCtrl">
    someGlobalVar value: {{someGlobalVar}}
  </p>

</div>


这实际上并没有扩展。这就像定义全局变量,该变量在许多文件/上下文中必须是唯一的。
ZachB 2015年

我没有看到缩放问题,但是在其他情况下,将范围变量称为“ root”可能不是更好的选择
Nico Westerdale

状态挂起的时间比需要它的组件子树的生存时间长,这也有点麻烦。
Roboprog

0

我相信我最近也有类似的难题

function parentCtrl() {
   var pc = this; // pc stands for parent control
   pc.foobar = 'SomeVal';
}

function childCtrl($scope) {

   // now how do I get the parent control 'foobar' variable?
   // I used $scope.$parent

   var parentFoobarVariableValue = $scope.$parent.pc.foobar;

   // that did it
}

我的设置有些不同,但同一件事可能仍然可以工作


0

从子组件中,您可以使用“ require”访问父组件的属性和方法。这是一个例子:

上级:

.component('myParent', mymodule.MyParentComponent)
...
controllerAs: 'vm',
...
var vm = this;
vm.parentProperty = 'hello from parent';

儿童:

require: {
    myParentCtrl: '^myParent'
},
controllerAs: 'vm',
...
var vm = this;
vm.myParentCtrl.parentProperty = 'hello from child';

0

超级容易并且可行,但是不确定为什么。

angular.module('testing')
  .directive('details', function () {
        return {
              templateUrl: 'components/details.template.html',
              restrict: 'E',                 
              controller: function ($scope) {
                    $scope.details=$scope.details;  <=== can see the parent details doing this                     
              }
        };
  });

-1

也许这很la脚,但您也可以将它们都指向某个外部对象:

var cities = [];

function ParentCtrl() {
    var vm = this;
    vm.cities = cities;
    vm.cities[0] = 'Oakland';
}

function ChildCtrl($scope) {
    var vm = this;
    vm.cities = cities;
}

这样做的好处是,ChildCtrl中的编辑现在会传播回父级中的数据。


引入全局变量很危险。
Dementic '18
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.