Misalkan saya memiliki komponen:
@Component({
selector: 'MyContainer',
template: `
<div class="container">
<!-- some html skipped -->
<ng-content></ng-content>
<span *ngIf="????">Display this if ng-content is empty!</span>
<!-- some html skipped -->
</div>`
})
export class MyContainer {
}
Sekarang, saya ingin menampilkan beberapa konten default jika <ng-content>
untuk komponen ini kosong. Adakah cara mudah untuk melakukan ini tanpa mengakses DOM secara langsung?
javascript
angular
Slawomir Dadas
sumber
sumber
Jawaban:
Gabungkan
ng-content
elemen HTML seperti adiv
untuk mendapatkan referensi lokal, lalu ikatngIf
ekspresi keref.children.length == 0
:template: `<div #ref><ng-content></ng-content></div> <span *ngIf="ref.nativeElement.childNodes.length == 0"> Display this if ng-content is empty! </span>`
sumber
ref.children.length
. childNodes akan berisitext
node jika Anda memformat html Anda dengan spasi atau baris baru, tetapi anak akan tetap kosong.ref.childNodes.length == 0
alih-alihref.children.length == 0
. Akan sangat membantu jika Anda dapat mengedit jawaban agar konsisten. Kesalahan mudah, bukan menghajar Anda. :)!ref.hasChildNodes()
alih-alihref.nativeElement.childNodes.length == 0
Ada beberapa yang hilang dalam jawaban @pixelbits. Kita tidak hanya perlu memeriksa
children
properti, karena setiap jeda baris atau spasi di template induk akan menyebabkanchildren
elemen dengan teks kosong \ linebreaks. Lebih baik periksa.innerHTML
dan.trim()
itu.Contoh kerja:
<span #ref><ng-content></ng-content></span> <span *ngIf="!ref.innerHTML.trim()"> Content if empty </span>
sumber
element.children.length
atauelement.childnodes.length
, tergantung pada apa yang ingin Anda minta.EDIT 17.03.2020
CSS murni (2 solusi)
Menyediakan konten default jika tidak ada yang diproyeksikan ke ng-content.
Penyeleksi yang memungkinkan:
:only-child
pemilih. Lihat posting ini di sini :: Only-child SelectorYang ini membutuhkan lebih sedikit kode / markup. Dukungan sejak IE 9: Can I Use: only-child
:empty
pemilih. Baca lebih lanjut.Dukungan dari IE 9 dan sebagian sejak IE 7/8: https://caniuse.com/#feat=css-sel3
HTML
<div class="wrapper"> <ng-content select="my-component"></ng-content> </div> <div class="default"> This shows something default. </div>
CSS
.wrapper:not(:empty) + .default { display: none; }
Seandainya itu tidak berfungsi
Ketahuilah, bahwa memiliki setidaknya satu spasi kosong dianggap tidak kosong. Angular menghapus spasi, tetapi untuk berjaga-jaga jika tidak:
<div class="wrapper"><!-- --><ng-content select="my-component"></ng-content><!-- --></div>
atau
<div class="wrapper"><ng-content select="my-component"></ng-content</div>
sumber
empty
pseudoclass css<loader [data]="allDataWeNeed"> <desired-component *loadingRender><desired-component> <other-default-component *renderWhenEmptyResult></other-default-component> </loader>
dan dalam komponen pemuatan, Anda dapat menunjukkan pemuatan kinerja yang dirasakan, sementara data sedang dimuat. Anda dapat menulis / menyelesaikannya dengan berbagai cara. Ini adalah salah satu demonstrasi bagaimana Anda bisa menyelesaikannya.Saat Anda memasukkan konten, tambahkan variabel referensi:
dan di kelas komponen Anda dapatkan referensi ke konten yang diinjeksi dengan @ContentChild ()
@ContentChild('content') content: ElementRef;
jadi di template komponen Anda, Anda dapat memeriksa apakah variabel konten memiliki nilai
<div> <ng-content></ng-content> <span *ngIf="!content"> Display this if ng-content is empty! </span> </div>
sumber
<MyContainer></MyContainer>
. Solusi Anda mengharapkan pengguna untuk membuat sub-elemen di bawah MyContainer:<MyContainer><div #content></div></MyContainer>
. Meskipun ini adalah kemungkinan, saya tidak akan mengatakan ini lebih baik.Suntikkan
elementRef: ElementRef
dan periksa apakahelementRef.nativeElement
memiliki anak. Ini mungkin hanya bekerja denganencapsulation: ViewEncapsulation.Native
.Bungkus
<ng-content>
label dan periksa apakah ada anak-anak. Ini tidak berhasilencapsulation: ViewEncapsulation.Native
.<div #contentWrapper> <ng-content></ng-content> </div>
dan periksa apakah memiliki anak
@ViewChild('contentWrapper') contentWrapper; ngAfterViewInit() { contentWrapper.nativeElement.childNodes... }
(tidak diuji)
sumber
@ViewChild
. Meskipun "Legal", ViewChild tidak boleh digunakan untuk mengakses node anak di dalam template. Ini adalah antipattern karena, sementara orang tua mungkin tahu tentang anak-anak, mereka tidak boleh berpasangan dengan mereka karena biasanya mengarah ke Pathological Coupling ; bentuk yang lebih tepat dari pengangkutan data atau penanganan permintaan adalah dengan menggunakan metodologi yang digerakkan oleh peristiwa .@ViewChild
. Terima kasih telah menambahkan keseimbangan pada komentar saya - Saya menemukan kedua komentar kami sama layaknya untuk dipertimbangkan seperti yang lain.@ViewChild()
berasal dari nama. "Anak-anak" belum tentu anak-anak, mereka hanyalah bagian deklaratif dari komponen (seperti yang saya lihat). Jika contoh komponen yang dibuat untuk markup ini adalah akses, ini tentu saja cerita yang berbeda, karena akan memerlukan pengetahuan tentang setidaknya antarmuka publik mereka dan ini akan benar-benar membuat hubungan yang erat. Ini adalah pembahasan yang sangat menarik. Saya khawatir bahwa saya tidak punya cukup waktu untuk memikirkan hal-hal seperti itu karena dengan kerangka seperti itu terlalu sering waktu habis untuk menemukan cara sama sekali.Jika Anda ingin menampilkan konten default mengapa Anda tidak menggunakan pemilih 'anak tunggal' dari css.
https://www.w3schools.com/cssref/sel_only-child.asp
misalnya: HTML
<div> <ng-content></ng-content> <div class="default-content">I am deafult</div> </div>
css
.default-content:not(:only-child) { display: none; }
sumber
Dengan Angular 10, ini sedikit berubah. Anda akan menggunakan:
<div #ref><ng-content></ng-content></div> <span *ngIf="ref.children.length == 0"> Display this if ng-content is empty! </span>
sumber
Dalam kasus saya, saya harus menyembunyikan induk dari ng-konten kosong:
<span class="ml-1 wrapper"> <ng-content> </ng-content> </span>
Pekerjaan css sederhana:
.wrapper { display: inline-block; &:empty { display: none; } }
sumber
Saya telah menerapkan solusi dengan menggunakan dekorator @ContentChildren , yang entah bagaimana mirip dengan jawaban @ Lerner.
Menurut dokumen , dekorator ini:
Jadi kode yang diperlukan dalam komponen induk adalah:
<app-my-component> <div #myComponentContent> This is my component content </div> </app-my-component>
Di kelas komponen:
@ContentChildren('myComponentContent') content: QueryList<ElementRef>;
Kemudian, di template komponen:
<div class="container"> <ng-content></ng-content> <span *ngIf="*ngIf="!content.length""><em>Display this if ng-content is empty!</em></span> </div>
Contoh lengkap : https://stackblitz.com/edit/angular-jjjdqb
Saya telah menemukan solusi ini diimplementasikan dalam komponen sudut, untuk
matSuffix
, dalam komponen bidang formulir .Dalam situasi ketika konten komponen dimasukkan nanti, setelah aplikasi diinisialisasi, kita juga dapat menggunakan implementasi reaktif, dengan berlangganan ke
changes
peristiwaQueryList
:export class MyComponentComponent implements AfterContentInit, OnDestroy { private _subscription: Subscription; public hasContent: boolean; @ContentChildren('myComponentContent') content: QueryList<ElementRef>; constructor() {} ngAfterContentInit(): void { this.hasContent = (this.content.length > 0); this._subscription = this.content.changes.subscribe(() => { // do something when content updates // this.hasContent = (this.content.length > 0); }); } ngOnDestroy() { this._subscription.unsubscribe(); } }
Contoh lengkap : https://stackblitz.com/edit/angular-essvnq
sumber