Search code examples
javascriptangulartypescriptclick

Angular 8 - click event not firing inside ngFor when iterating over object arrays


NOTE: Original post edited to remove implemention details/complexity.

I have an ngFor loop that calls a method on a service. The method returns an array that is iterated over by the for loop.

The click event binding does not work if the returned array is an array of objects. It does work if the array is of a primitive type.

***contextmenu/right-click does work in either case, so this is affecting click and not contextmenu

***click events immediately before and after this for work as expected

***the behavior is the same even if I move the hardcoded method from the service to the component

Here is the for loop in context:

<div><span (click)="addVariable()"></span></div> <!-- works -->

<div *ngFor="let variable of designerService.getVariables();" (click)="onLeftClick()" (contextmenu)="onRightClick()">just a simple div</div> <!-- doesnt work -->

<div><span (click)="addVariable()"></span></div> <!-- works -->
public addVariable() {
  alert("add variable");
}

public onLeftClick() {
  alert("left click");
}

public onRightClick() {
  alert("right click");
}

With this implementation (or any other object type array) click will not work/fire:

public getVariables(): {name: string}[] {
  return [{"name": "dog"},{"name": "cat"},{"name": "bird"},{"name":"bear"}];
}

With this implementation click will work:

public getVariables(): number[] {
  return [1,2,3,4,5];
}

Super simple, doesn't work...

Any ideas on what might be the problem? I'm at the end of my rope with Angular at this point.


Solution

  • Try this:

    // YourComponent ts file
    variables: {name: string}[];
    
    constructor(public designerService: DesignerService) { }
    
    ngOnInit() {
      this.variables = this.designerService.getVariables();
    }
    
    // Other methods
    
    <!-- HTML template file -->
    <!-- Replace the designerService.getVariables() method call with component property 'variables' -->
    <div *ngFor="let variable of variables" (click)="onLeftClick()" 
    (contextmenu)="onRightClick()">works</div> <!-- works -->
    

    There might be some code within the application that is triggering Change Detection which is causing re-rendering even before the associated click handler executes and hence the issue.

    Just for testing purpose, before making the above suggested change you can also try to define an array property within the service class and then return that array from getVariables(), and observe if it resolves the issue.

    // DesignerService ts file
    someArray = [{"name": "dog"},{"name": "cat"},{"name": "bird"},{"name":"bear"}];
    
    public getVariables(): {name: string}[] {
      return this.someArray;
    }