@HostBinding with a variable class in Angular

Solution 1:

This can't be made variable.

What you can do instead is to bind to the class property directly

@HostBinding('class') classes = 'class1 class2 class3';

Solution 2:

If you have a limited number of classes you can conditionally add each one:

@HostBinding('class.c1') get c1 () { return this.useC1; } 
@HostBinding('class.c2') get c2 () { return this.useC2; }

Note that .c1 and .c2 need to be defined outside the component.

Plunker

Solution 3:

I have to contradict the other answers, there is not a reason why binding class.foo shouldn't work. Actually, the following format works properly:

@HostBinding('class.foo') variableName = true;

If it doesn't work in your case, you might need to add a scope to your CSS class (you can see a discussion here).

The problem is that HostBinding only sees the host scope, it means that it only sees the classes and the id applied to the component itself, not to its children. So when you write your CSS, you need to specify that CSS belongs to the component itself (the host pseudoelement).

According to Angular documentation:

Use the :host pseudo-class selector to target styles in the element that hosts the component (as opposed to targeting elements inside the component's template).

You can easily specify the host scope just adding :host before your CSS rule:

:host.foo { // It only matches <Component class="foo">
  /* Your CSS here */
}

In place of

.foo { // It matches any <element class="foo" /> inside <Component>
  /* Your CSS here */
}

If you want, I created a working Plunker that you can see clicking here

Solution 4:

Günter's answer isn't really helpful in case of already having some class names bound to a variable.

A good way to combine variable string class names with boolean style predefined class names is to use the classnames npm package.

Use it together with the @HostBinding and a setter function to get amazing results:

import * as classNames from 'classnames';

(...)

@HostBinding('class') get classes(): string {
  return classNames(this.getDynamicClassName(), {
    'is-open': this.isOpen,
    'has-children': this.hasChildren
  });
}