Reputation: 83
I'm trying to figure out what is happening in my program and I really don't understand. Before I jump to the problem, for the purpose of this question I simplified the code and I conducted some tests, to make sure that I localized the problem.
So, in my component.html
file I have this piece of code:
<div *ngFor="let item of entityDetails | keyvalue">
<div *ngIf="hasConflict(item.key)">text</div>
</div>
As you can see I'm using *ngFor
together with Angular KeyVauePipe
and inside I check a condition using *ngIf
.
Entity Details
is a json that I get through http
request using Promise
and it looks like this:
{rcn: "1912330", name: "Barcelona supercomputing Center", vatNumber: "ESS090000099D", category: "Research Organisation", categoryCode: "REC"}
In component.ts
, the declaration:
public entityDetails: string[] = new Array();
and the retrieving the data:
this.service.getEntityDetails().then(data => {
this.entityDetails = data;
});
In hasConflict
method, all I do is printout:
hasConflict(item): Boolean {
let check: boolean = false;
console.log("test");
return check;
}
When I run it and open the console, I can already see a bunch of printouts:
but then once I click anywhere on the website or I use scroll, they intensify, after one mouse click:
after quick scroll:
Any help will be appreciated.
Upvotes: 0
Views: 168
Reputation: 281
As suggested in the comments [@Chellappan] you should use a pipe. Function calling inside ngif
is what causes the problem due to angular's change detection triggering.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'hasConflict' })
export class HasConflictPipe implements PipeTransform {
transform (value: any, type: string, ): boolean {
console.log('test');
return value ? true : false;
}
}
and then inside your template
<div *ngFor="let item of entityDetails | keyvalue">
<div *ngIf="item.key | hasConflict">text</div>
</div>
Obviously you should place your logic inside hasConflict
that is specific to your case.
Upvotes: 0
Reputation: 3267
This is happening beacuse you are calling a function from template. So every time angular's change detection runs, it updates the UI and calls the function again.
Instead of calling a function from template, Prepare a map inside subscribe of getEntryDetails which you could use in template directly to check for the condition. For example:
conflictMap = {};
if(condition){
conflictMap[key] = value;
}
and then directly in html:
<div *ngFor="let item of entityDetails | keyvalue">
<div *ngIf="conflictMap[item.key]">text</div>
</div>
Further reading - using a function in *ngIf runs several times instead of once
Upvotes: 1