angularangular-directiveangular2-hostbinding

Angular HostBinding in a custom directive not working inside an *ngFor


I have created a custom directive that adds / removes a class selector with a click event. Should be pretty straight forward, and it works fine as long as I'm using the directive outside an ngFor loop. The directive is composed of the code below:

import { Directive, HostBinding, HostListener, Input } from '@angular/core';
@Directive({
    selector: '[appFav]'
})
export class FavDirective {
    @HostBinding('class.isFav') isFav:boolean = false;

    @HostListener('click') onClick() {
        this.isFav = !this.isFav;
        console.log('clicked');
    }
    @Input() set appFav(val:boolean) {
        this.isFav = val;
    }
}

And I'm trying to use that directive on a button inside a Cards component. So inside the Cards Component's html template the buttons code looks like that:

<div class="favBtn" appFav><span class="material-icons">favorite_border</span></div>

This works when I'm using the component on its own, but when I generate multiple cards using the ngFor loop like below the decorator doesn't seem to work anymore.

<custom-card class="card" *ngFor="let card of getCards()"></custom-card>

The isFav property in the directive is fixed and the .isFav class selector is not added when I inspect the button. Though the console.log messages display properly which means that the onClick method in the directive does run.

Any help would be much appreciated. Thanks in advance.


Solution

  • Right now angular is not able to differentiate b/w components if you see elements panel you click on a button all the instance get updated. so to assign a unique key to all the elements in loop so that angular can differentiate them.

    --Try below code you will get expected behavior:

    in you app.component.html -- Add a trackBy that function will assign unique key

      <app-media-item *ngFor="let mi of getMediaItems(); trackBy:trackBytitle"
                      [mediaItem]='mi'
                      (interact)='hdlMediaItem($event)' 
      >
      </app-media-item>
    

    and in you app.component.ts -- right now title seems unique to me so i return title part.

    trackBytitle(index: number, mediaObj: any): string {
    return mediaObj.title; // title is unique or return something unique 
    }