Come aggiungere "class" all'elemento host?


190

Non so come aggiungere al mio componente <component></component>un attributo di classe dinamica ma all'interno del modello html (component.html).

L'unica soluzione che ho trovato è quella di modificare l'elemento tramite l'elemento nativo "ElementRef". Questa soluzione sembra un po 'complicata per fare qualcosa che dovrebbe essere molto semplice.

Un altro problema è che i CSS devono essere definiti al di fuori dell'ambito dei componenti, interrompendo l'incapsulamento dei componenti.

C'è una soluzione più semplice? Qualcosa come <root [class]="..."> .... </ root>all'interno del modello.

Risposte:


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

Esempio di Plunker

In questo modo non è necessario aggiungere il CSS al di fuori del componente. CSS mi piace

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

funziona dall'interno del componente e il selettore viene applicato solo se la classe someClassè impostata sull'elemento host.


Ho dovuto fare l' someField = truein ngOnInit()-Metodo anziché ngAfterViewInit(). Altrimenti non avrei potuto farlo funzionare.
Giovanni

Ho fatto una forcella qui che mostra la :hostparte reale funzionante. Dove posso saperne di più sul parametro host in @Component () decorator (la sintassi non è ovvia per me e la documentazione di @Component non spiega molto ) o saperne di più sul tuo HostBinding preferito (è elencato solo come interfaccia su Angular2 site?)
The Red Pea

Non conosco documenti migliori, ma è solo un modo diverso di fare quello che puoi fare@Input() @Output() @HostBinding() @HostListener() @ViewChild(ren)() @ContentChild(ren)()
Günter Zöchbauer

1
usa un getter con un nome diverso per l'associazione host che restituisce il valore invertito@HostBinding('class.xxx') get xxxclass(){ return !this.someField;}
Günter Zöchbauer

1
@YochaiAkoka non sono sicuro di cosa ti riferisci. Non sono a conoscenza di questa regola. Meno è di solito più, quindi se puoi evitare di aggiungere elementi aggiuntivi, dovresti evitarlo.
Günter Zöchbauer,

184

La risposta di Günter è ottima (la domanda è l' attributo di classe dinamica ) ma ho pensato di aggiungere solo per completezza ...

Se stai cercando un modo rapido e pulito per aggiungere una o più classi statiche all'elemento host del tuo componente (ad esempio, per scopi di stile del tema) puoi semplicemente fare:

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

E se usi una classe sul tag entry, Angular unirà le classi, ovvero

<my-component class="someClass2">
  I have both someClass1 & someClass2 applied to me
</my-component>

1
Adoro questo per semplicità. Tuttavia nel mio caso l'elemento host è incapsulato con un attributo diverso, chiamiamolo ngcontent_hostdi uno qualsiasi degli attributi sugli elementi nel mio template , let's call those ngcontent_template , so if I put a style in the styleUrls` del mio componente, non influenzeranno l'elemento host perché non influenzeranno ngcontent_host, loro può influenzare solo gli elementi del modello; possono solo influenzare ngcontent_template. Mi sbaglio? Qualche suggerimento su questo? Immagino di poter sempre girareViewEncapsulation.None
The Red Pea

11
Un altro modo è quello di saltare la variabile @HostBinding('class.someClass') true;. Puoi persino farlo da qualsiasi classe estesa dal tuo componente.
adamdport,

3
Per aggiungere più classi puoi fare l'host: {'[class]': '"class1 class2"'}
jbojcic l'

4
Se usi l'host: {}variante, potresti voler impostare use-host-property-decoratorsu falsein tslint.json. Altrimenti riceverai avvisi IDE. @adamdport Quel metodo non funziona (più). Utilizzo di Angular 5.2.2 nella nostra app.
Ruud Voost,

1
Sono solo io o il vecchio modo sembra migliore del nuovo modo? Sono sicuro che avessero buone ragioni per migrare, ma meh ...
schiaccia l'

13

Puoi semplicemente aggiungere @HostBinding('class') class = 'someClass';all'interno della tua classe @Component .

Esempio:

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

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

  constructor() {}      

  ngOnInit() {}
}

1
La className direttiva può anche essere utilizzato ed è meglio evitare di usare classcome nome di variabile (dal momento che si potrebbe fare riferimento a esso e modificarlo in seguito). Esempio: @HostBinding('className') myTheme = 'theme-dark';.
CPHPython


0

Ecco come l'ho fatto (Angular 7):

Nel componente, aggiungi un input:

@Input() componentClass: string = '';

Quindi nel modello HTML del componente aggiungi qualcosa di simile:

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

E infine nel modello HTML in cui istanza il componente:

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

Disclaimer: sono abbastanza nuovo per Angular, quindi potrei essere solo fortunato qui!


2
Leggermente necro ma: questo non aggiunge la classe CSS all'elemento host - che è l'elemento per il <root>tag, non tutto ciò che aggiungi al modello dell'elemento.
millimoose
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.