angularangular-directiveangular2-hostbinding

Angular 2+ append class in directive


I have Angular 6.0.0 application. Need to dynamically append classes to html elements. Ideally, this should be implemented via directive. Currently I have something like this and it works OK.

<div class="class1 prefix-{{variable}}"></div>

I want to make the prefix reusable and I am trying to reach the better result by using a directive:

html:

<div class="class1" [appendBusinessLogicClass]="variable"></div>

appendBusinessLogicClass.directive.ts:

export class AppendBusinessLogicClass {
readonly prefix = 'prefix';
  @HostBinding('class') class = ''; // this clears the html class1
  @Input('appendBusinessLogicClass') set appendBusinessLogicClass(variable: string) {
      this.class = this.prefix + '-' + variable;
   }
}

But the HostBinding CLEARS class1 in the html code. But I'd like to APPEND 'prefix-rand' to the class list. Note, that we do not know variable at the compile time.

Thanks


Solution

  • What you're actually doing now is binding to the class attribute, so basically the value will be set to this.class, which is completely fine. However, it turns out you're not actually getting the initial value from the 'class' attribute and this means no matter whatever you set class to be on your template, the value will always be overwritten. So basically Angular is taking over setting that class attribute.

    So, what you have to do is get a reference of that value in the class attribute. In Angular you can actually consider any html attribute to be an input to your component/directive, the only thing you have to do is annotate it with an @Input decorator. Here we're saving the value of the class attribute to defaultClassList and then using it to compute the new class attribute value, so your code could look like this:

    export class AppendBusinessLogicClass {
        readonly prefix = 'prefix';
    
        @Input('class')
        defaultClassList;// `class` is a keyword so we're calling it defaultClassList instead
    
        @HostBinding('class')
        classList;// `class` is a keyword so we're calling it classList instead
    
        @Input('appendBusinessLogicClass') set appendBusinessLogicClass(variable: string) {
            this.classList = this.defaultClassList + " " + this.prefix + '-' + variable;
        }
    }
    

    So to sum up, you end up getting the attribute value defined in your template and including it in your bound this.classList whenever the value you pass to the directive is set.