0

enter image description here

I'm trying to add 'active' class to all the divs (options in this case) that are clicked and remove the class on a second click.

The options count can vary as it's generated by ngFor.

HTML

<div [ngClass]="{'active': selectedOptions == i}" *ngFor="let opt of options; let i=index"
 (click)="answerSelectedMultiple(i)">

TS

answerSelectedMultiple(index){
    if(this.selectedOptions.indexOf(index) == -1){
        this.selectedOptions.push(index);
    }else{
        this.selectedOptions.splice(this.selectedOptions.indexOf(index), 1);
    }
}
Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73
Akash Agrawal
  • 2,219
  • 1
  • 17
  • 38

2 Answers2

1

You could capsulate this into a directive:

@Directive({
  selector: '[activeOnClick]',
  // Optionally replace this both with properties marked 
  // with @HostBinding and @HostListener decorators
  host: {
    '[class.active]': 'clicked',
    '(click)': '_toggle()'
  }
})
export class ActiveOnClickDirective {
   @Input('activeOnClick')
   clicked = false;

   _toggle(){
      this.clicked= !this.clicked;
   }
}

After declaring the directive in a module, it could be used as follows:

<div activeOnClick *ngFor="let opt of options; let i=index">

In the case that you want to bind the flag value of the directive in the template:

<div [activeOnClick]="true" *ngFor="let opt of options; let i=index">

You could even expand this to dynamically apply different classes on the host element:

@Directive({
  selector: '[classesOnClick]'
})
export class ClassesOnClickDirective { 
   @Input('classesOnClick')
   clicked = false;

   @Input()
   set class(value: string[]| string){
      let classes = Array.isArray(value) ? value : value.split(' ');
      classes = classes.filter(class => !!class);
      this._classes = classes;
   }
   private _classes: string [] = ['active'];

   constructor(private element: ElementRef, private renderer: Renderer2){}

   @HostListener('click')
   _toggle(){
      this.clicked = !this.clicked;
   }

   private _update(){
     this._classes.forEach(class => {
       if(this.clicked){
          this.renderer.addClass(this.element.nativeElement, class);
       }else{
          this.renderer.removeClass(this.element.nativeElement, class);
       } 
     });
   }
}

Then use as follows:

<div [classesOnClick]="true" [classesOnClickClass]="['c1','c2']" *ngFor="let opt of options; let i=index">

<div [classesOnClick]="true" classesOnClickClass="c1 c2" *ngFor="let opt of options; let i=index">
Jota.Toledo
  • 27,293
  • 11
  • 59
  • 73
0

You can record active status on opt:

<div *ngFor="let opt of options" [ngClass]="{active: opt.active}"
  (click)="opt.active = !opt.active">
Explosion Pills
  • 188,624
  • 52
  • 326
  • 405