AngularJS mengakses lingkup induk dari pengontrol anak

382

Saya telah mengatur pengontrol saya menggunakan data-ng-controller="xyzController as vm"

Saya memiliki skenario dengan pengendali bersarang induk / anak. Saya tidak punya masalah mengakses properti induk di html bersarang dengan menggunakan $parent.vm.property, tetapi saya tidak tahu cara mengakses properti induk dari dalam pengontrol anak saya.

Saya sudah mencoba menyuntikkan $ scope dan kemudian menggunakan $scope.$parent.vm.property , tetapi ini tidak berfungsi?

Adakah yang bisa memberikan saran?

zpydee
sumber

Jawaban:

620

Jika HTML Anda seperti di bawah ini Anda dapat melakukan sesuatu seperti ini:

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

Kemudian Anda dapat mengakses lingkup induk sebagai berikut

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

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

Jika Anda ingin mengakses controller induk dari tampilan Anda, Anda harus melakukan sesuatu seperti ini:

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

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

Memperbarui

Sebenarnya karena Anda mendefinisikan citiesdalam kontroler induk, kontroler anak Anda akan mewarisi semua variabel lingkup. Jadi secara teori Anda tidak perlu menelepon $parent. Contoh di atas juga dapat ditulis sebagai berikut:

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

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

Dokumen AngularJS menggunakan pendekatan ini, di sini Anda dapat membaca lebih lanjut tentang $scope.

Pembaruan lain

Saya pikir ini adalah jawaban yang lebih baik untuk poster aslinya.

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

Jika Anda menggunakan controller asmetode ini, Anda juga dapat mengakses lingkup induk sebagai berikut

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

Seperti yang Anda lihat ada banyak cara berbeda dalam mengakses $scopes.

Biola diperbarui

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>

Dieterg
sumber
6
Saya pikir dua masalah dengan pembaruan terakhir Anda adalah 1. Mewarisi lingkup induk dapat memiliki potensi konflik namespace, dan 2. Membutuhkan pengetahuan bahwa alias pengendali orangtua adalah 'pc'. Ini membuat penggunaan ulang menjadi lebih sulit.
tchen
2
Anda mendefinisikan pengontrol sebagai fungsi CtrlName (...) {} tetapi bagaimana kita dapat mencapainya dengan menggunakan nomenklatur Angular? seperti: angular.module (MdlName) .controller (CtrlName, function (...) {});
Pedro Justo
1
Apa maksudmu? Kontroler hanyalah sebuah fungsi? yaituangular.module('app').controller('ParentCtrl', ParentCtrl);
Dieterg
1
maaf kamu benar! Dalam metode 'controller as', menggunakan '$ scope.pc.cities;' Bagi saya, untuk mengakses kota orang tua merupakan 'langkah mundur' karena jika di childCtrl kita tidak memiliki properti 'kota' maka akan secara otomatis mengakses kota orang tua. Tidak ada cara lain untuk menyelesaikan masalah ini?
Pedro Justo
46

Saya baru saja memeriksa

$scope.$parent.someProperty

bekerja untukku.

dan itu akan terjadi

{{$parent.someProperty}}

untuk tampilan.

Stepan Suvorov
sumber
hmmm, tidak bekerja untuk saya. Bertanya-tanya apakah itu ada hubungannya dengan controller sebagai sintaks vm.
zpydee
Jika Anda telah menamai pengontrol induk maka Anda akan menjatuhkan $ parent di templat dan memiliki {{vm.someProperty}}
solbs
8

Saat Anda menggunakan assintaks, seperti ParentController as parentCtrl, untuk mendefinisikan pengontrol kemudian untuk mengakses variabel lingkup induk di pengontrol anak gunakan sebagai berikut:

var id = $scope.parentCtrl.id;

Dimana parentCtrlnama pengendali induk menggunakan assintaks dan idmerupakan variabel yang didefinisikan dalam pengontrol yang sama.

Rubi saini
sumber
2

Beberapa kali Anda mungkin perlu memperbarui properti induk secara langsung dalam lingkup anak. mis. perlu menyimpan tanggal dan waktu kontrol orangtua setelah perubahan oleh pengontrol anak. mis. Kode di 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) {

    }
Gayan Pathirage
sumber
1

Anda juga dapat menghindari pewarisan ruang lingkup dan menyimpan barang-barang di ruang lingkup "global".

Jika Anda memiliki pengontrol utama dalam aplikasi Anda yang membungkus semua pengontrol lain, Anda dapat menginstal "pengait" ke lingkup global:

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

Kemudian di pengontrol anak, Anda dapat mengakses ruang lingkup "global" dengan $scope.root. Apa pun yang Anda atur di sini akan terlihat secara global.

Contoh:

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>

rustyx
sumber
Ini tidak benar-benar skala. Ini seperti mendefinisikan variabel global yang harus unik di banyak file / konteks.
ZachB
Saya tidak melihat masalah penskalaan, tetapi menyebut variabel lingkup sesuatu selain 'root' mungkin lebih baik dalam konteks lain
Nico Westerdale
Ini juga agak menyusahkan untuk memiliki status yang bertahan lebih lama dari umur komponen sub-pohon yang membutuhkannya.
Roboprog
0

Saya percaya saya memiliki masalah serupa baru-baru ini

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
}

Pengaturan saya sedikit berbeda, tetapi hal yang sama mungkin masih berfungsi

Benjamin Thvedt
sumber
0

Dari komponen anak, Anda dapat mengakses properti dan metode komponen induk dengan 'memerlukan'. Berikut ini sebuah contoh:

Induk:

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

Anak:

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

Sangat mudah dan berfungsi, tetapi tidak yakin mengapa ....

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                     
              }
        };
  });
John Peters
sumber
-1

Mungkin ini lumpuh tetapi Anda juga bisa mengarahkan keduanya ke beberapa objek eksternal:

var cities = [];

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

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

Manfaatnya di sini adalah bahwa pengeditan di ChildCtrl sekarang mendukung kembali ke data di induk.

Peter Hollingsworth
sumber
memperkenalkan variabel global berbahaya.
Demensik