Saya mencoba belajar Angular 2.
Saya ingin mengakses komponen anak dari komponen induk menggunakan Anotasi @ViewChild .
Berikut beberapa baris kode:
Di BodyContent.ts saya punya:
import {ViewChild, Component, Injectable} from 'angular2/core';
import {FilterTiles} from '../Components/FilterTiles/FilterTiles';
@Component({
selector: 'ico-body-content'
, templateUrl: 'App/Pages/Filters/BodyContent/BodyContent.html'
, directives: [FilterTiles]
})
export class BodyContent {
@ViewChild(FilterTiles) ft:FilterTiles;
public onClickSidebar(clickedElement: string) {
console.log(this.ft);
var startingFilter = {
title: 'cognomi',
values: [
'griffin'
, 'simpson'
]}
this.ft.tiles.push(startingFilter);
}
}
saat di FilterTiles.ts :
import {Component} from 'angular2/core';
@Component({
selector: 'ico-filter-tiles'
,templateUrl: 'App/Pages/Filters/Components/FilterTiles/FilterTiles.html'
})
export class FilterTiles {
public tiles = [];
public constructor(){};
}
Akhirnya di sini templat (seperti yang disarankan dalam komentar):
BodyContent.html
<div (click)="onClickSidebar()" class="row" style="height:200px; background-color:red;">
<ico-filter-tiles></ico-filter-tiles>
</div>
FilterTiles.html
<h1>Tiles loaded</h1>
<div *ngFor="#tile of tiles" class="col-md-4">
... stuff ...
</div>
Templat FilterTiles.html dimuat dengan benar ke tag ico-filter-tiles (memang saya bisa melihat tajuknya).
Catatan: kelas BodyContent disuntikkan ke dalam templat lain (Tubuh) menggunakan DynamicComponetLoader: dcl.loadAsRoot (BodyContent, '# ico-bodyContent', injector):
import {ViewChild, Component, DynamicComponentLoader, Injector} from 'angular2/core';
import {Body} from '../../Layout/Dashboard/Body/Body';
import {BodyContent} from './BodyContent/BodyContent';
@Component({
selector: 'filters'
, templateUrl: 'App/Pages/Filters/Filters.html'
, directives: [Body, Sidebar, Navbar]
})
export class Filters {
constructor(dcl: DynamicComponentLoader, injector: Injector) {
dcl.loadAsRoot(BodyContent, '#ico-bodyContent', injector);
dcl.loadAsRoot(SidebarContent, '#ico-sidebarContent', injector);
}
}
Masalahnya adalah ketika saya mencoba menulis ft
ke log konsol, saya dapat undefined
, dan tentu saja saya mendapatkan pengecualian ketika saya mencoba untuk mendorong sesuatu di dalam array "ubin": 'tidak ada ubin properti untuk "tidak terdefinisi" .
Satu hal lagi: Komponen FilterTiles tampaknya dimuat dengan benar, karena saya dapat melihat templat html untuk itu.
Ada saran? Terima kasih
sumber
ft
tidak akan diatur dalam konstruktor, tetapi dalam event handler klik itu akan sudah ditetapkan.loadAsRoot
, yang memiliki masalah yang diketahui dengan deteksi perubahan. Hanya untuk memastikan coba gunakanloadNextToLocation
atauloadIntoLocation
.loadAsRoot
. Setelah saya diganti denganloadIntoLocation
masalah terpecahkan. Jika Anda membuat komentar sebagai jawaban, saya dapat menandainya sebagai diterimaJawaban:
Saya memiliki masalah yang sama dan berpikir saya akan memposting kalau-kalau ada orang yang membuat kesalahan yang sama. Pertama, satu hal yang perlu dipertimbangkan adalah
AfterViewInit
; Anda harus menunggu tampilan diinisialisasi sebelum Anda dapat mengakses@ViewChild
. Namun, saya@ViewChild
masih mengembalikan nol. Masalahnya adalah masalah saya*ngIf
. The*ngIf
direktif membunuh saya komponen kontrol jadi saya tidak bisa referensi itu.Semoga itu bisa membantu.
EDIT
Seperti yang disebutkan oleh @Ashg di bawah ini , solusinya adalah menggunakan
@ViewChildren
alih-alih@ViewChild
.sumber
ngClass
+hidden
class sebagai gantingIf
. Itu berhasil. Terima kasih!Masalah seperti yang disebutkan sebelumnya adalah
ngIf
yang menyebabkan pandangan menjadi tidak terdefinisi. Jawabannya adalah menggunakanViewChildren
alih-alihViewChild
. Saya memiliki masalah serupa di mana saya tidak ingin grid ditampilkan sampai semua data referensi telah dimuat.html:
Kode Komponen
Di sini kami menggunakan
ViewChildren
di mana Anda dapat mendengarkan perubahan. Dalam hal ini ada anak dengan referensi#searchGrid
. Semoga ini membantu.sumber
this.SearchGrid
properti Anda harus menggunakan sintaks inginsetTimeout(()=>{ ///your code here }, 1);
menghindari Pengecualian: Ekspresi telah berubah setelah diperiksa*ngIf
berfungsi, dan setelah render kita dapat menyimpan ElementRef dari komponen dinamis.Anda dapat menggunakan setter untuk
@ViewChild()
Jika Anda memiliki pembungkus ngIf, penyetel akan dipanggil dengan tidak terdefinisi, dan sekali lagi dengan referensi begitu ngIf memungkinkannya merender.
Masalah saya adalah sesuatu yang lain. Saya belum memasukkan modul yang berisi "FilterTiles" saya di app.modules saya. Templat tidak melempar kesalahan tetapi referensi selalu tidak ditentukan.
sumber
FilterTiles
. Saya pernah mengalami masalah itu karena alasan itu sebelumnya.@ViewChild('paginator', {static: false})
Ini berhasil untuk saya.
Komponen saya bernama 'komponen saya', misalnya, ditampilkan menggunakan * ngIf = "showMe" seperti:
Jadi, ketika komponen diinisialisasi komponen belum ditampilkan sampai "showMe" benar. Jadi, referensi @ViewChild saya semuanya tidak terdefinisi.
Di sinilah saya menggunakan @ViewChildren dan QueryList yang dikembalikan. Lihat artikel sudut pada QueryList dan demo penggunaan @ViewChildren .
Anda dapat menggunakan QueryList yang dikembalikan @ViewChildren dan berlangganan setiap perubahan pada item yang direferensikan menggunakan rxjs seperti yang terlihat di bawah ini. @ViewChild tidak memiliki kemampuan ini.
Semoga ini bisa membantu seseorang menghemat waktu dan frustrasi.
sumber
.take(1).subscribe()
, tetapi jawaban yang bagus, terima kasih banyak!Solusi saya adalah menggunakan
[style.display]="getControlsOnStyleDisplay()"
alih-alih*ngIf="controlsOn"
. Blok ada tetapi tidak ditampilkan.sumber
Yang memecahkan masalah saya adalah memastikan
static
diatur kefalse
.Dengan
static
dimatikan,@ViewChild
referensi diperbarui oleh Angular ketika*ngIf
direktif berubah.sumber
Solusi saya adalah menggantinya
*ngIf
dengan[hidden]
. Kelemahannya adalah semua komponen anak hadir dalam kode DOM. Tetapi bekerja untuk kebutuhan saya.sumber
Dalam kasus saya, saya mempunyai setter variabel input menggunakan
ViewChild
, dan bagianViewChild
dalam*ngIf
direktif, sehingga setter mencoba mengaksesnya sebelum*ngIf
diberikan (itu akan berfungsi dengan baik tanpa*ngIf
, tetapi tidak akan berfungsi jika selalu diatur ke benar dengan*ngIf="true"
).Untuk menyelesaikannya, saya menggunakan Rxjs untuk memastikan referensi apa pun yang
ViewChild
menunggu hingga tampilan dimulai. Pertama, buat Subjek yang selesai ketika setelah view init.Kemudian, buat fungsi yang mengambil dan menjalankan lambda setelah subjek selesai.
Akhirnya, pastikan referensi ke ViewChild menggunakan fungsi ini.
sumber
Itu harus bekerja.
Tapi seperti yang dikatakan Günter Zöchbauer pasti ada masalah lain dalam template. Saya telah membuat agak Relevant-Plunkr-Answer . Tolong jangan periksa konsol browser.
boot.ts
filterTiles.ts
Itu bekerja seperti pesona. Harap periksa tag dan referensi Anda.
Terima kasih...
sumber
Ini berfungsi untuk saya, lihat contoh di bawah ini.
sumber
Saya memiliki masalah serupa, di mana
ViewChild
ada di dalamswitch
klausa yang tidak memuat elemen viewChild sebelum direferensikan. Saya memecahkannya dengan cara semi-hacky tetapi membungkusViewChild
referensi dengansetTimeout
yang dieksekusi segera (yaitu 0ms)sumber
Solusi saya untuk ini adalah memindahkan ngIf dari luar komponen anak ke dalam komponen anak pada div yang membungkus seluruh bagian html. Dengan cara itu masih tersembunyi ketika perlu, tetapi mampu memuat komponen dan saya bisa referensi di induknya.
sumber
Saya memperbaikinya hanya menambahkan SetTimeout setelah mengatur komponen yang terlihat
HTML saya:
Komponen JS saya
sumber
Dalam kasus saya, saya tahu komponen anak akan selalu ada, tetapi ingin mengubah keadaan sebelum menginisialisasi anak untuk menyelamatkan pekerjaan.
Saya memilih untuk menguji untuk anak sampai muncul dan membuat perubahan segera, yang menyelamatkan saya siklus perubahan pada komponen anak.
Secara peringatan, Anda dapat menambahkan jumlah upaya maksimal atau menambahkan beberapa penundaan ms ke
setTimeout
.setTimeout
secara efektif melemparkan fungsi ke bagian bawah daftar operasi yang tertunda.sumber
Semacam pendekatan umum:
Anda dapat membuat metode yang akan menunggu hingga
ViewChild
siapPemakaian:
sumber
Bagi saya masalahnya adalah saya mereferensikan ID pada elemen.
Alih-alih seperti ini:
sumber
Jika Anda menggunakan Ionic, Anda harus menggunakan
ionViewDidEnter()
kait siklus hidup. Ionik berjalan beberapa hal tambahan (terutama animasi-terkait) yang biasanya menyebabkan kesalahan tak terduga seperti ini, maka kebutuhan untuk sesuatu yang berjalan setelahngOnInit
,ngAfterContentInit
dan sebagainya.sumber
Inilah sesuatu yang berhasil untuk saya.
Jadi saya pada dasarnya menetapkan cek setiap detik sampai
*ngIf
menjadi benar dan kemudian saya melakukan hal-hal yang berkaitan dengan sayaElementRef
.sumber
Solusi yang berhasil bagi saya adalah menambahkan arahan dalam deklarasi di app.module.ts
sumber