0

I'm trying to understand why hovering on item in child invoke method from parent component. Here is example link

I have parent component that pass items into child component (list) like this:

<app-list [items]="getItems()"></app-list>
...
  items = [
    {
      label: 'test',
    },
    {
      label: 'foo',
    },
  ];

  getItems(): any[] {
    console.log('getItems');
    return this.items;
  }

in app-list component:

<li *ngFor="let item of items" (mouseover)="onMouseOverOption(item)" role="option">
  <span>{{ item.label }}</span>
</li>

  onMouseOverOption(item) {
    console.log("onMouseOverOption", item);
  }

And every time when I'm hovering on list item method getItems() is invoked - twice. Can someone explain this behavior to me?

Thanks

surzyn
  • 131
  • 1
  • 11
  • Check this: https://stackoverflow.com/questions/41645325/mouseover-and-mouseout-trigger-multiple-times – NeNaD Apr 05 '21 at 18:11

2 Answers2

1

It's called Angular Detection Changes system. You can learn more about it here: https://medium.com/showpad-engineering/why-you-should-never-use-function-calls-in-angular-template-expressions-e1a50f9c0496

Dharman
  • 30,962
  • 25
  • 85
  • 135
JackyShows
  • 191
  • 1
  • 10
1

This is because of the ngOnChanges() method. Whenever you use a function in ngFor or ngIf, this is the problem that occurs.

Its always safe and better to use a variable, because, its value doesnot change always but when you call a method, whenever you are doing (mouseover), it will get the return the items and call the same method one more time.

Easy solution for this ==> Dont call the getItems() method but directly, assign the items variable.

I changed it in the stackblitz: Please take a look:

https://stackblitz.com/edit/angular-ivy-7aupnm?embed=1&file=src/app/list/list.component.ts

The change can be seen in app.component.html.

Srikar Phani Kumar M
  • 1,069
  • 1
  • 3
  • 8
  • Thank you for response, I've used method getItems because I need to do some transformation on items in array. I'll do it in other place like onchange. Also the weird part for me is that the onchange lifecycle method is never called on hover so why the getItems method is called – surzyn Apr 05 '21 at 18:48
  • 1
    If that is the case, you can use call by reference, method and manipulate data and then get it back and store it in a new variable. Check out this stackblitz: https://stackblitz.com/edit/angular-ivy-7aupnm?embed=1&file=src/app/list/list.component.ts .. I made changes in app.component.ts and app.component.html – Srikar Phani Kumar M Apr 05 '21 at 18:52
  • You can modify whatever you would like and then return a local variable and assign it to a new variable / existing variable. You need not use ngOnChanges. ngOnChanges needs to be used only when there is an input stream of changes. Here that is not the case i assume. – Srikar Phani Kumar M Apr 05 '21 at 18:53
  • basically this array is an property of input element and it may change during time so I think that the best solution will be to use ngOnChange – surzyn Apr 05 '21 at 18:59
  • Oh ok then. you have 2 ways to go about it, – Srikar Phani Kumar M Apr 05 '21 at 19:00