I dont't know how to add to my component <component></component> a dynamic class attribute but inside the template html (component.html).
The only solution I found is to modify the item via "ElementRef" native element. That solution seems a little complicated to do something that should be very simple.
Another problem is that CSS has to be defined outside component scope, breaking component encapsulation.
Is there a simpler solution? Something like <root [class]="..."> .... </ root> inside the template.
9 Answers
This way you don't need to add the CSS outside of the component:
@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(); } } This CSS is defined inside the component and the selector is only applied if the class someClass is set on the host element (from outside):
:host(.someClass) { background-color: red; } 11Günter's answer is great (question is asking for dynamic class attribute) but I thought I would add just for completeness...
If you're looking for a quick and clean way to add one or more static classes to the host element of your component (i.e., for theme-styling purposes) you can just do:
@Component({ selector: 'my-component', template: 'app-element', host: {'class': 'someClass1'} }) export class App implements OnInit { ... } And if you use a class on the entry tag, Angular will merge the classes, i.e.,
<my-component> I have both someClass1 & someClass2 applied to me </my-component> 13You can simply add @HostBinding('class') class = 'someClass'; inside your @Component class.
Example:
@Component({ selector: 'body', template: 'app-element' }) export class App implements OnInit { @HostBinding('class') class = 'someClass'; constructor() {} ngOnInit() {} } 2If you want to add a dynamic class to your host element, you may combine your HostBinding with a getter as
@HostBinding('class') get class() { return aComponentVariable } Another problem is that CSS has to be defined outside component scope, breaking component encapsulation
This is not true. With scss (SASS) you can easily style the component (itself;host) as so:
:host { display: block; position: absolute; width: 100%; height: 100%; pointer-events: none; visibility: hidden; &.someClass { visibility: visible; } } This way the encapsulation is "unbroken".
1for multiple classes situation, as @jbojcic mentioned above, you can use:
host: {class: 'A B C'}
In addition to @JoshuaDavid answer, there is another way to define static class, which works on angular v8 when I tried (might also work on older versions):
@Component({ selector: "my-component.someClass1.someClass2", ... }) which will generate following output:
<my-component> ... </my-component> you can also just use this way:
@Component({ selector: ".someClass1.someClass2", ... }) which will generate following output:
<div> ... </div> 1this is what I did:
import { Component, Attribute, HostBinding } from "@angular/core"; @Component({ selector: "selector-el", template: ... }) export class MyComponent { @HostBinding('class') get classAttribute(): string { let defaultClasses = 'selector-el-class'; return defaultClasses + ' ' + this.classNames; } constructor( @Attribute('class') public classNames: string ) { } } 1Here's how I did it (Angular 7):
In the component, add an input:
@Input() componentClass: string = ''; Then in the component's HTML template add something like:
<div [ngClass]="componentClass">...</div> And finally in the HTML template where you instance the component:
<root componentClass="someclass someotherclass">...</root> Disclaimer: I'm fairly new to Angular, so I might be just getting lucky here!
1