Bagaimana cara menambahkan "kelas" ke elemen host?

190

Saya tidak tahu bagaimana cara menambahkan atribut kelas<component></component> dinamis ke komponen saya tetapi di dalam templat html (component.html).

Satu-satunya solusi yang saya temukan adalah memodifikasi item melalui elemen asli "ElementRef". Solusi itu tampaknya agak rumit untuk melakukan sesuatu yang seharusnya sangat sederhana.

Masalah lain adalah bahwa CSS harus didefinisikan di luar lingkup komponen, melanggar enkapsulasi komponen.

Apakah ada solusi yang lebih sederhana? Sesuatu seperti <root [class]="..."> .... </ root>di dalam templat.

laskarayf
sumber

Jawaban:

296
@Component({
   selector: 'body',
   template: 'app-element',
   // prefer decorators (see below)
   // host:     {'[class.someClass]':'someField'}
})
export class App implements OnInit {
  constructor(private cdRef:ChangeDetectorRef) {}

  someField: boolean = false;
  // alternatively also the host parameter in the @Component()` decorator can be used
  @HostBinding('class.someClass') someField: boolean = false;

  ngOnInit() {
    this.someField = true; // set class `someClass` on `<body>`
    //this.cdRef.detectChanges(); 
  }
}

Contoh plunker

Dengan cara ini Anda tidak perlu menambahkan CSS di luar komponen. Seperti CSS

:host(.someClass) {
  background-color: red;
}

bekerja dari bagian dalam komponen dan pemilih hanya diterapkan jika kelas someClassdiatur pada elemen host.

Günter Zöchbauer
sumber
Saya harus melakukan someField = truedi- metode ngOnInit()bukan ngAfterViewInit(). Saya tidak bisa membuatnya bekerja sebaliknya.
John
Membuat garpu di sini yang menunjukkan bagian yang sebenarnya :hostberfungsi. Di mana saya dapat mempelajari lebih lanjut tentang parameter host di @Component () dekorator (sintaksinya tidak jelas bagi saya, dan dokumentasi @Component tidak menjelaskan banyak hal ) atau mempelajari lebih lanjut tentang HostBinding pilihan Anda (hanya terdaftar sebagai Antarmuka di Situs Angular2?)
The Red Pea
Saya tidak tahu dokumen yang lebih baik, tetapi itu hanya cara berbeda untuk melakukan apa yang dapat Anda lakukan dengan@Input() @Output() @HostBinding() @HostListener() @ViewChild(ren)() @ContentChild(ren)()
Günter Zöchbauer
1
gunakan pengambil dengan nama yang berbeda untuk pengikatan host yang mengembalikan nilai terbalik@HostBinding('class.xxx') get xxxclass(){ return !this.someField;}
Günter Zöchbauer
1
@YochaiAkoka tidak yakin apa yang Anda rujuk. Saya tidak mengetahui aturan ini. Lebih sedikit biasanya lebih, jadi jika Anda dapat menghindari menambahkan elemen tambahan, maka Anda harus menghindarinya.
Günter Zöchbauer
184

Jawaban Günter bagus (pertanyaannya adalah meminta atribut kelas dinamis ) tapi saya pikir saya akan menambahkan hanya untuk kelengkapan ...

Jika Anda mencari cara cepat dan bersih untuk menambahkan satu atau lebih kelas statis ke elemen host komponen Anda (yaitu, untuk keperluan penataan tema) Anda bisa melakukannya:

@Component({
   selector: 'my-component',
   template: 'app-element',
   host: {'class': 'someClass1'}
})
export class App implements OnInit {
...
}

Dan jika Anda menggunakan kelas pada tag entri, Angular akan menggabungkan kelas, yaitu,

<my-component class="someClass2">
  I have both someClass1 & someClass2 applied to me
</my-component>
JoshuaDavid
sumber
1
Cintai ini untuk kesederhanaan. Namun dalam kasus saya elemen host dienkapsulasi dengan atribut yang berbeda, sebut saja itu ngcontent_hostdaripada atribut pada elemen di template saya , let's call those ngcontent_template , so if I put a style in the styleUrls` dari komponen saya, mereka tidak akan mempengaruhi elemen host karena mereka tidak akan mempengaruhi ngcontent_host, mereka hanya dapat memengaruhi elemen template; mereka hanya dapat mempengaruhi ngcontent_template. Apakah saya salah? Ada saran tentang ini? Saya kira saya selalu bisa mengubahViewEncapsulation.None
The Red Pea
11
Cara lain adalah dengan hanya melewatkan variabel @HostBinding('class.someClass') true;,. Anda bahkan dapat melakukan ini dari kelas apa pun yang diperluas komponen Anda.
adamdport
3
Untuk menambahkan beberapa kelas, Anda dapat melakukan host: {'[class]': '"class1 class2"'}
jbojcic
4
Jika Anda menggunakan host: {}varian, Anda mungkin ingin set use-host-property-decoratorpengaturan untuk falsedi tslint.json. Kalau tidak, Anda akan menerima peringatan IDE. @adamdport Metode itu tidak berfungsi (lagi). Menggunakan Angular 5.2.2 di aplikasi kami.
Ruud Voost
1
Apakah hanya saya, atau apakah cara lama tampak lebih baik daripada cara baru? Saya yakin mereka punya alasan bagus untuk bermigrasi, tetapi saya ...
naksir
13

Anda bisa menambahkan @HostBinding('class') class = 'someClass';di dalam kelas @Component Anda .

Contoh:

@Component({
   selector: 'body',
   template: 'app-element'       
})
export class App implements OnInit {

  @HostBinding('class') class = 'someClass';

  constructor() {}      

  ngOnInit() {}
}
Mike D3ViD Tyson
sumber
1
The className direktif juga dapat digunakan dan lebih baik untuk menghindari menggunakan classsebagai nama variabel (karena Anda mungkin referensi dan mengubahnya nanti). Contoh: @HostBinding('className') myTheme = 'theme-dark';.
CPHPython
3

Jika Anda ingin menambahkan kelas dinamis ke elemen host Anda, Anda dapat menggabungkan Anda HostBindingdengan pengambil sebagai

@HostBinding('class') get class() {
    return aComponentVariable
}

Stackblitz demo di https://stackblitz.com/edit/angular-dynamic-hostbinding

Saksham
sumber
0

Inilah cara saya melakukannya (Sudut 7):

Dalam komponen, tambahkan input:

@Input() componentClass: string = '';

Kemudian di dalam templat HTML komponen tambahkan sesuatu seperti:

<div [ngClass]="componentClass">...</div>

Dan akhirnya di templat HTML tempat Anda membuat instance komponen:

<root componentClass="someclass someotherclass">...</root>

Penafian: Saya cukup baru di Angular, jadi saya mungkin beruntung di sini!

zippycoder
sumber
2
Tapi sedikit necro: ini tidak menambahkan kelas CSS ke elemen host - yang merupakan elemen untuk <root>tag, tidak apa pun yang Anda tambahkan ke template elemen.
milimoose