AngularJS truy cập phạm vi cha từ bộ điều khiển con


382

Tôi đã thiết lập bộ điều khiển của mình bằng cách sử dụng data-ng-controller="xyzController as vm"

Tôi có một kịch bản với các bộ điều khiển lồng nhau cha / con. Tôi không gặp vấn đề gì khi truy cập các thuộc tính cha mẹ trong html lồng nhau bằng cách sử dụng $parent.vm.property, nhưng tôi không thể tìm ra cách truy cập thuộc tính cha mẹ từ bên trong trình điều khiển con của mình.

Tôi đã thử tiêm phạm vi $ và sau đó sử dụng $scope.$parent.vm.property, nhưng điều này không hiệu quả?

Bất cứ ai có thể cung cấp lời khuyên?

Câu trả lời:


620

Nếu HTML của bạn giống như bên dưới, bạn có thể làm một cái gì đó như thế này:

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

Sau đó, bạn có thể truy cập phạm vi cha mẹ như sau

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

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

Nếu bạn muốn truy cập bộ điều khiển chính từ chế độ xem của mình, bạn phải làm một cái gì đó như thế này:

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

Xem jsFiddle: http://jsfiddle.net/2r728/

Cập nhật

Thực tế vì bạn đã xác định citiestrong trình điều khiển chính, trình điều khiển con của bạn sẽ kế thừa tất cả các biến phạm vi. Vì vậy, về mặt lý thuyết bạn không phải gọi $parent. Ví dụ trên cũng có thể được viết như sau:

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

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

Các tài liệu AngularJS sử dụng phương pháp này, ở đây bạn có thể đọc thêm về $scope.

Một cập nhật khác

Tôi nghĩ rằng đây là một câu trả lời tốt hơn cho các poster ban đầu.

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>

Mã não

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

Nếu bạn sử dụng controller asphương thức, bạn cũng có thể truy cập phạm vi cha như sau

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

Như bạn có thể thấy có nhiều cách khác nhau trong việc truy cập $scopes.

Cập nhật fiddle

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
Tôi nghĩ rằng hai vấn đề với bản cập nhật cuối cùng của bạn là 1. Kế thừa phạm vi cha có thể có xung đột không gian tên tiềm năng và 2. Yêu cầu kiến ​​thức rằng bí danh của bộ điều khiển chính là 'pc'. Điều này làm cho việc sử dụng lại khó khăn hơn.
15:51

2
Bạn đã xác định bộ điều khiển là hàm CtrlName (...) {} nhưng làm thế nào chúng ta có thể đạt được điều đó bằng cách sử dụng danh pháp góc? như: angular.module (MdlName) .controll (CtrlName, function (...) {});
Pedro Justo

1
Ý anh là gì? Một bộ điều khiển chỉ là một chức năng? tức làangular.module('app').controller('ParentCtrl', ParentCtrl);
Dieterg

1
xin lỗi, bạn nói đúng Trong phương thức 'trình điều khiển dưới dạng', sử dụng '$ scope.pc.cities;' để truy cập vào các thành phố của cha mẹ dường như là một 'bước lùi' bởi vì nếu ở childCtrl, chúng ta không có tài sản 'thành phố' thì nó sẽ tự động truy cập vào các thành phố của cha mẹ. Không có cách nào khác để giải quyết vấn đề này?
Pedro Justo


46

Tôi vừa mới kiểm tra

$scope.$parent.someProperty

làm việc cho tôi

Và nó sẽ là

{{$parent.someProperty}}

để xem


hmmm, không làm việc cho tôi Tự hỏi nếu nó phải làm với bộ điều khiển như cú pháp vm.
zpydee

Nếu bạn đã đặt tên cho trình điều khiển chính thì bạn sẽ bỏ $ cha trong mẫu và có {{vm.someProperty}}
giải quyết

8

Khi bạn đang sử dụng ascú pháp, như ParentController as parentCtrl, để xác định bộ điều khiển sau đó để truy cập biến phạm vi cha trong bộ điều khiển con, hãy sử dụng như sau:

var id = $scope.parentCtrl.id;

Trong trường hợp parentCtrllà tên của bộ điều khiển cha mẹ sử dụng ascú pháp và idlà một biến được định nghĩa trong cùng một bộ điều khiển.


2

Đôi khi bạn có thể cần cập nhật thuộc tính cha mẹ trực tiếp trong phạm vi con. ví dụ cần lưu ngày và thời gian kiểm soát cha mẹ sau khi thay đổi bởi bộ điều khiển con. ví dụ: Mã trong 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>

Mã não

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

    function Child($scope) {

    }

1

Bạn cũng có thể phá vỡ sự kế thừa phạm vi và lưu trữ mọi thứ trong phạm vi "toàn cầu".

Nếu bạn có một bộ điều khiển chính trong ứng dụng của mình, nó bao bọc tất cả các bộ điều khiển khác, bạn có thể cài đặt một "hook" vào phạm vi toàn cầu:

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

Sau đó, trong bất kỳ trình điều khiển con nào, bạn có thể truy cập phạm vi "toàn cầu" với $scope.root. Bất cứ điều gì bạn đặt ở đây sẽ được hiển thị trên toàn cầu.

Thí dụ:

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>


Điều này không thực sự quy mô. Nó giống như xác định các biến toàn cục phải là duy nhất trên nhiều tệp / ngữ cảnh.
ZachB

Tôi không thấy vấn đề mở rộng, nhưng gọi biến phạm vi là một cái gì đó khác với 'root' có thể tốt hơn trong các bối cảnh khác
Nico Westerdale

Nó cũng có một chút phiền toái khi có trạng thái tồn tại lâu hơn thời gian sống của cây con thành phần cần nó.
Roboprog

0

Tôi tin rằng tôi đã có một quandary tương tự gần đây

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
}

Thiết lập của tôi hơi khác một chút, nhưng điều tương tự có lẽ vẫn hoạt động


0

Từ một thành phần con, bạn có thể truy cập các thuộc tính và phương thức của thành phần cha mẹ với 'yêu cầu'. Đây là một ví dụ:

Cha mẹ:

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

Đứa trẻ:

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

0

Siêu dễ dàng và hoạt động, nhưng không chắc tại sao ....

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

Có lẽ điều này là khập khiễng nhưng bạn cũng có thể chỉ cả hai vào một số đối tượng bên ngoài:

var cities = [];

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

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

Lợi ích ở đây là các chỉnh sửa trong ChildCtrl hiện đang quay trở lại dữ liệu trong phần gốc.


giới thiệu các biến toàn cầu là nguy hiểm.
Mất trí nhớ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.