Wie füge ich dem Host-Element "Klasse" hinzu?


187

Ich weiß nicht, wie ich meiner Komponente <component></component>ein dynamisches Klassenattribut hinzufügen soll, aber innerhalb der Vorlage html (component.html).

Die einzige Lösung, die ich gefunden habe, besteht darin, das Element über das native Element "ElementRef" zu ändern. Diese Lösung scheint etwas kompliziert zu sein, um etwas zu tun, das sehr einfach sein sollte.

Ein weiteres Problem besteht darin, dass CSS außerhalb des Komponentenbereichs definiert werden muss, wodurch die Komponentenkapselung unterbrochen wird.

Gibt es eine einfachere Lösung? So etwas wie <root [class]="..."> .... </ root>in der Vorlage.

Antworten:


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

Plunker Beispiel

Auf diese Weise müssen Sie das CSS nicht außerhalb der Komponente hinzufügen. CSS wie

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

funktioniert von der Innenseite der Komponente und der Selektor wird nur angewendet, wenn die Klasse someClassfür das Host-Element festgelegt ist.


Ich musste stattdessen die someField = truein- ngOnInit()Methode machen ngAfterViewInit(). Ich könnte es sonst nicht zum Laufen bringen.
John

Habe hier eine Gabel gemacht, die zeigt, wie das eigentliche :hostTeil funktioniert. Wo kann ich mehr über Host - Parameter in @Component () Dekorateur (die Syntax nicht mir klar ist, und die @Component Dokumentation erklärt nicht sehr viel ) oder mehr über Ihren bevorzugten HostBinding lernen (es nur ist als Schnittstelle aufgelistet auf Angular2 Seite?)
Die rote Erbse

Ich kenne keine besseren Dokumente, aber es ist nur eine andere Art, das zu tun, was man machen kann@Input() @Output() @HostBinding() @HostListener() @ViewChild(ren)() @ContentChild(ren)()
Günter Zöchbauer

1
Verwenden Sie einen Getter mit einem anderen Namen für die Host-Bindung, die den invertierten Wert zurückgibt@HostBinding('class.xxx') get xxxclass(){ return !this.someField;}
Günter Zöchbauer

1
@ YochaiAkoka nicht sicher, worauf Sie sich beziehen. Diese Regel ist mir nicht bekannt. Weniger ist normalerweise mehr. Wenn Sie also das Hinzufügen zusätzlicher Elemente vermeiden können, sollten Sie dies vermeiden.
Günter Zöchbauer

184

Günters Antwort ist großartig (Frage fragt nach dynamischen Klassenattributen), aber ich dachte, ich würde nur der Vollständigkeit halber hinzufügen ...

Wenn Sie nach einer schnellen und sauberen Möglichkeit suchen , dem Host-Element Ihrer Komponente eine oder mehrere statische Klassen hinzuzufügen (dh zu Zwecken der Themengestaltung), können Sie einfach Folgendes tun:

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

Wenn Sie eine Klasse für das Eintragstag verwenden, führt Angular die Klassen zusammen, d. H.

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

1
Ich liebe dies der Einfachheit halber. In meinem Fall ist das Host-Element jedoch mit einem anderen Attribut gekapselt. Nennen wir es ngcontent_hosteines der Attribute für Elemente in meiner Vorlage , let's call those ngcontent_template , so if I put a style in the styleUrls` meiner Komponente. Sie wirken sich nicht auf das Host-Element aus, da sie sich nicht auf ngcontent_hostsie auswirken kann nur Vorlagenelemente beeinflussen; Sie können nur beeinflussen ngcontent_template. Irre ich mich Irgendwelche Vorschläge dazu? Ich denke, ich könnte mich immer umdrehenViewEncapsulation.None
The Red Pea

11
Eine andere Möglichkeit besteht darin, die Variable einfach zu überspringen @HostBinding('class.someClass') true;. Sie können dies sogar von jeder Klasse aus tun, die Ihre Komponente erweitert.
Adamdport

3
Um mehrere Klassen hinzuzufügen, können Sie Folgendes tun: {'[class]': '"class1 class2"'}
jbojcic

4
Wenn Sie die host: {}-Variante verwenden, möchten Sie möglicherweise die use-host-property-decoratorEinstellung auf falsein setzen tslint.json. Andernfalls erhalten Sie IDE-Warnungen. @adamdport Diese Methode funktioniert (nicht mehr). Verwenden von Angular 5.2.2 in unserer App.
Ruud Voost

1
Ist es nur ich oder scheint der alte Weg besser als der neue? Ich bin sicher, sie hatten gute Gründe zu migrieren, aber meh ...
Crush

11

Sie können einfach @HostBinding('class') class = 'someClass';in Ihre @Component hinzufügen Klasse .

Beispiel:

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

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

  constructor() {}      

  ngOnInit() {}
}

1
Die className- Direktive kann auch verwendet werden, und es ist besser, die Verwendung classals Variablenname zu vermeiden (da Sie möglicherweise darauf verweisen und sie später ändern). Beispiel : @HostBinding('className') myTheme = 'theme-dark';.
CPHPython


0

So habe ich es gemacht (Angular 7):

Fügen Sie in der Komponente eine Eingabe hinzu:

@Input() componentClass: string = '';

Fügen Sie dann in der HTML-Vorlage der Komponente Folgendes hinzu:

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

Und schließlich in der HTML-Vorlage, in der Sie die Komponente instanziieren:

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

Haftungsausschluss: Ich bin ziemlich neu in Angular, also habe ich hier vielleicht Glück!


2
Etwas nekrotisch, aber: Dadurch wird die CSS-Klasse nicht zum Host-Element hinzugefügt. Dies ist das Element für das <root>Tag und nichts, was Sie der Elementvorlage hinzufügen.
Millimoose
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.