Perbarui variabel lingkup induk di AngularJS

113

Saya memiliki dua pengontrol, satu dibungkus satu sama lain. Sekarang saya tahu lingkup anak mewarisi properti dari lingkup induk tetapi apakah ada cara untuk memperbarui variabel lingkup induk? Sejauh ini saya belum menemukan solusi yang jelas.

Dalam situasi saya, saya memiliki pengontrol kalender dalam formulir. Saya ingin memperbarui tanggal mulai dan akhir dari lingkup induk (yang merupakan formulir) sehingga formulir tersebut memiliki tanggal mulai dan berakhir saat dikirimkan.

Malcr001
sumber
sepertinya pengontrol kalender Anda harus menjadi arahan.
Yunus

Jawaban:

193

Anda perlu menggunakan objek (bukan primitif) dalam lingkup induk dan kemudian Anda akan dapat memperbaruinya langsung dari lingkup anak

Induk:

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

Anak:

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

Demo kerja : http://jsfiddle.net/sh0ber/xxNxj/

Lihat Apa nuansa dari scope prototypal / prototypical inheritance di AngularJS?

Dan
sumber
1
Saya mendapatkan kesalahan ini saat mencoba menerapkan ini: 'Tidak dapat menyetel properti' properti induk 'tidak ditentukan'.
Malcr001
Bisakah Anda memposting kode Anda? Ini berfungsi di demo biola. Jika kontrol kalender Anda menggunakan cakupan isolate, itu tidak akan mewarisi dari lingkup induk, jadi Anda harus meneruskan nilai ke lingkup direktif.
Dan
Maaf saya lupa tentang pertanyaan ini. Saya telah menerimanya karena pada akhirnya saya berhasil membuatnya bekerja dengan bantuan jawaban ini.
Malcr001
Saya memahami menempatkan {{parentobj.parentproperty}} dalam elemen div ctrlParent adalah apa yang mendeklarasikan objek parentobj dan menyetel objek ini sebagai dalam cakupan ctrlParent. Apakah ini asumsi yang tepat ?
Stephane
1
Terima kasih, ini berhasil! Saya pasti harus membaca ini (prototipe enheritance dan primitif). Dapatkah Anda merekomendasikan bacaan yang bagus yang menjelaskan sedikit lebih banyak daripada tautan SO Anda?
jvannistelrooy
116

Ada satu cara lagi untuk melakukan tugas ini dan tidak menggunakan $scope.$parentvariabel.

Persiapkan saja metode untuk mengubah nilai dalam lingkup induk dan gunakan di anak satu. Seperti ini:

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

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

Ini juga berfungsi dan memberi Anda lebih banyak kendali atas perubahan nilai.

Anda kemudian dapat juga memanggil metode bahkan dalam HTML seperti: <a ng-click="changeSimpleValue('y')" href="#">click me!</a>.

Ravbaker
sumber
1
Solusi yang bagus! ini berfungsi karena ketika sesuatu tidak ditemukan di $ scope saat ini, Angular mencari di $ parent satu. docs.angularjs.org/guide/scope (lihat 'Scope Hierarchies').
Elo
Saya suka jawaban ini, tidak perlu membuat objek yang tidak perlu.
grimmdude
3
Pembaca masa depan: Semua komentar lima besar ini agak salah arah. Membuat dua fungsi penyetel (yang merupakan "objek yang tidak perlu") untuk setiap variabel adalah turunan warisan yang kikuk dan tidak perlu dan bukan cara Angular. Misko Hevery, pencipta Angular, memberikan ceramah di mana dia mengajarkan "Setiap kali Anda memiliki model-ng pasti ada titik di sana di suatu tempat. Jika Anda tidak memiliki titik, Anda salah melakukannya.” Video Misko @ 29:19
Dan
bagaimana saya bisa menerapkan solusi ini dengan menggunakan sintaks controllerAS?
niran
6

Ini juga berfungsi (tetapi tidak yakin apakah ini mengikuti praktik terbaik atau tidak)

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

app.controller('ctrlChild',function($scope){
    $scope.$parent.simpleValue = 'y';
});
DynamicNate
sumber
1
Anda benar, menggunakan $ scope. $ Parent.value akan berfungsi dalam banyak kasus, namun biasanya bukan ide terbaik untuk digunakan secara ekstensif karena bisa jadi sulit untuk dikelola dalam proyek yang lebih besar dan lebih rumit.
Alex Johnson
4

Saat Anda menetapkan atribut primitif ke lingkup, itu selalu lokal ke lingkup (mungkin dibuat dengan cepat), bahkan jika lingkup induk memiliki atribut dengan nama yang sama. Ini adalah keputusan desain, dan IMHO yang bagus.

Jika Anda perlu mengubah beberapa primitif (ints, boolean, string) di lingkup induk, dari tampilan, Anda memerlukannya menjadi atribut objek lain dalam lingkup itu, sehingga tugas dapat membaca:

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

dan itu akan, pada gilirannya:

  1. dapatkan viewDataobjek dari ruang lingkup apa pun yang didefinisikan
  2. tetapkan 4 ke myAttratributnya.
ditulis ulang
sumber
4

Untuk mengakses variabel yang dideklarasikan di induk, kita harus menggunakan $ parent di pengontrol anak atau file template

Dalam pengontrol

$scope.$parent.varaiable_name

Dalam template html

ng-model="$parent.varaiable_name"
Nibu
sumber