Saya tahu saya bukan yang pertama bertanya tentang hal ini, tetapi saya tidak dapat menemukan jawaban dalam pertanyaan sebelumnya. Saya memiliki ini dalam satu komponen
<div class="col-sm-5">
<laps
[lapsData]="rawLapsData"
[selectedTps]="selectedTps"
(lapsHandler)="lapsHandler($event)">
</laps>
</div>
<map
[lapsData]="rawLapsData"
class="col-sm-7">
</map>
Dalam controller rawLapsdata
akan dimutasi dari waktu ke waktu.
Dalam laps
, data adalah output sebagai HTML dalam format tabel. Ini berubah setiap kali rawLapsdata
berubah.
map
Komponen saya perlu digunakan ngOnChanges
sebagai pemicu untuk menggambar ulang marker di Google Map. Masalahnya adalah ngOnChanges tidak menyala ketika ada rawLapsData
perubahan pada induknya. Apa yang dapat saya?
import {Component, Input, OnInit, OnChanges, SimpleChange} from 'angular2/core';
@Component({
selector: 'map',
templateUrl: './components/edMap/edMap.html',
styleUrls: ['./components/edMap/edMap.css']
})
export class MapCmp implements OnInit, OnChanges {
@Input() lapsData: any;
map: google.maps.Map;
ngOnInit() {
...
}
ngOnChanges(changes: { [propName: string]: SimpleChange }) {
console.log('ngOnChanges = ', changes['lapsData']);
if (this.map) this.drawMarkers();
}
Pembaruan: ngOnChanges tidak berfungsi, tetapi sepertinya lapsData sedang diperbarui. Di ngInit adalah pendengar acara untuk perubahan zoom yang juga memanggil this.drawmarkers
. Ketika saya mengubah zoom, saya memang melihat perubahan pada marker. Jadi satu-satunya masalah adalah saya tidak mendapatkan notifikasi pada saat input data berubah.
Pada orang tua, saya memiliki baris ini. (Ingat bahwa perubahan tercermin dalam putaran, tetapi tidak di peta).
this.rawLapsData = deletePoints(this.rawLapsData, this.selectedTps);
Dan perhatikan bahwa this.rawLapsData
itu sendiri adalah pointer ke tengah objek json besar
this.rawLapsData = this.main.data.TrainingCenterDatabase.Activities[0].Activity[0].Lap;
zone.run(...)
harus dilakukan kemudian.ngOnChanges()
tidak akan dipanggil. Anda dapat menggunakanngDoCheck()
dan mengimplementasikan logika Anda sendiri untuk menentukan apakah isi array telah berubah.lapsData
diperbarui karena memiliki / merupakan referensi ke array yang sama denganrawLapsData
.Jawaban:
rawLapsData
terus menunjuk ke array yang sama, bahkan jika Anda memodifikasi konten array (misalnya, menambah item, menghapus item, mengubah item).Selama deteksi perubahan, ketika Angular memeriksa properti input komponen untuk perubahan, ia menggunakan (pada dasarnya)
===
untuk pemeriksaan kotor. Untuk array, ini berarti referensi array (hanya) kotor diperiksa. KarenarawLapsData
referensi array tidak berubah,ngOnChanges()
tidak akan dipanggil.Saya dapat memikirkan dua solusi yang mungkin:
Menerapkan
ngDoCheck()
dan melakukan logika deteksi perubahan Anda sendiri untuk menentukan apakah isi array telah berubah. (Doc Lifecycle Hooks memiliki contoh .)Tetapkan array baru
rawLapsData
setiap kali Anda membuat perubahan pada konten array. MakangOnChanges()
akan dipanggil karena array (referensi) akan muncul sebagai perubahan.Dalam jawaban Anda, Anda menemukan solusi lain.
Mengulangi beberapa komentar di sini di OP:
laps
komponen, kode / templat Anda berulang-ulang melewati setiap entri dalamlapsData
larik, dan menampilkan konten, sehingga ada ikatan sudut pada setiap bagian data yang ditampilkan.===
pengecekan), itu tetap (secara default) kotor memeriksa semua binding templat. Ketika ada yang berubah, Angular akan memperbarui DOM. Itu yang kamu lihat.maps
komponen mungkin tidak memiliki binding dalam template untuk nyalapsData
properti masukan, kan? Itu akan menjelaskan perbedaannya.Perhatikan bahwa
lapsData
di kedua komponen danrawLapsData
di komponen induk semua mengarah ke array yang sama / satu. Jadi meskipun Angular tidak melihat (referensi) perubahan padalapsData
properti input, komponen "dapatkan" / lihat perubahan isi array karena semuanya berbagi / referensi bahwa satu array. Kami tidak membutuhkan Angular untuk menyebarkan perubahan ini, seperti halnya dengan tipe primitif (string, angka, boolean). Tetapi dengan tipe primitif, setiap perubahan nilainya akan selalu memicungOnChanges()
- yang merupakan sesuatu yang Anda manfaatkan dalam jawaban / solusi Anda.Seperti yang Anda ketahui sekarang properti input objek memiliki perilaku yang sama dengan properti input array.
sumber
Bukan pendekatan terbersih, tetapi Anda hanya bisa mengkloning objek setiap kali Anda mengubah nilainya?
Saya pikir saya lebih suka pendekatan ini daripada menerapkan Anda sendiri
ngDoCheck()
tetapi mungkin seseorang seperti @ GünterZöchbauer bisa berpadu.sumber
Dalam Case of Arrays Anda dapat melakukannya seperti ini:
Dalam
.ts
file (komponen Induk) tempat Anda memperbarui,rawLapsData
lakukan seperti ini:Larutan:
dan
ngOnChanges
akan memanggil komponen anaksumber
Sebagai perpanjangan dari solusi kedua Mark Rajcok
Anda dapat mengkloning isi array seperti ini:
Saya menyebutkan ini karena
tidak bekerja untuk saya. Saya harap ini membantu.
sumber
Jika data berasal dari perpustakaan eksternal Anda mungkin perlu menjalankan pernyataan data upate dalam
zone.run(...)
. Suntikkanzone: NgZone
untuk ini. Jika Anda dapat menjalankan instantiation dari perpustakaan eksternal di dalamzone.run()
sudah, maka Anda mungkin tidak perluzone.run()
nanti.sumber
$scope.$apply
?zone.run
mirip dengan$scope.apply
.Gunakan
ChangeDetectorRef.detectChanges()
untuk memberi tahu Angular untuk menjalankan deteksi perubahan saat Anda mengedit objek yang bersarang (yang terlewatkan dengan pemeriksaan kotornya).sumber
Saya punya 2 solusi untuk menyelesaikan masalah Anda
ngDoCheck
untuk mendeteksiobject
data yang diubah atau tidakobject
ke alamat memori baru denganobject = Object.create(object)
dari komponen induk.sumber
Solusi 'hack' saya adalah
perubahan yang dipilih pada saat yang sama dengan rawLapsData dan yang memberikan peta kesempatan lain untuk mendeteksi perubahan melalui tipe primitif
objek yanglebih sederhana . BUKAN elegan, tapi berhasil.sumber
Ubah deteksi tidak dipicu saat Anda mengubah properti objek (termasuk objek bersarang). Salah satu solusinya adalah dengan menetapkan kembali referensi objek baru menggunakan fungsi 'lodash' clone ().
sumber
Ini hack yang baru saja membuat saya keluar dari masalah dengan yang ini.
Jadi skenario yang mirip dengan OP - Saya punya komponen Angular bersarang yang membutuhkan data yang diturunkan ke sana, tetapi input menunjuk ke sebuah array, dan seperti yang disebutkan di atas, Angular tidak melihat perubahan karena tidak memeriksa isi dari array.
Jadi untuk memperbaikinya saya mengubah array ke string untuk Angular untuk mendeteksi perubahan, dan kemudian di komponen bersarang saya membagi (',') string kembali ke array dan hari-hari bahagia lagi.
sumber
Saya menemukan kebutuhan yang sama. Dan saya banyak membaca tentang ini, inilah tembaga saya tentang masalah ini.
Jika Anda ingin deteksi perubahan Anda saat ditekan, maka Anda akan memilikinya ketika Anda mengubah nilai objek di dalam kan? Dan Anda juga akan memilikinya jika entah bagaimana, Anda menghapus objek.
Seperti yang sudah dikatakan, gunakan changeDetectionStrategy.onPush
Katakanlah Anda memiliki komponen yang Anda buat ini, dengan changeDetectionStrategy.onPush:
Maka Anda akan mendorong item dan memicu deteksi perubahan:
atau Anda akan menghapus item dan memicu deteksi perubahan:
atau Anda akan mengubah nilai attrbibute untuk suatu item dan memicu deteksi perubahan:
Konten penyegaran:
Metode slice mengembalikan Array yang sama persis, dan tanda [=] membuat referensi baru untuk itu, memicu deteksi perubahan setiap kali Anda membutuhkannya. Mudah dan mudah dibaca :)
Salam,
sumber
Saya telah mencoba semua solusi yang disebutkan di sini, tetapi untuk beberapa alasan
ngOnChanges()
masih tidak memecat saya. Jadi saya menyebutnyathis.ngOnChanges()
setelah memanggil layanan yang mengisi ulang array saya dan berfungsi .... benar? mungkin tidak. Rapi? tidak. Bekerja? Iya!sumber
ok jadi solusi saya untuk ini adalah:
Dan ini memicu saya ngOnChanges
sumber
Saya harus membuat retasan untuk itu -
sumber
Dalam kasus saya itu adalah perubahan nilai objek yang
ngOnChange
tidak ditangkap. Beberapa nilai objek dimodifikasi sebagai respons panggilan api. Inisialisasi ulang objek memperbaiki masalah dan menyebabkanngOnChange
pemicu di komponen anak.Sesuatu seperti
sumber