html - Angular ngFor körs i en oändlig loop när en array visas
Jag försöker för närvarande att skapa en Logbox för min webbapp. Den får en Array med loggar och ska visa dem rad för rad i en div. Jag använder ngFor och loopar igenom min Array med loggar och sedan visar dem.
Mitt problem nu är att loggarna visas oändligt många gånger, inte bara 5 gånger (5 arrayposter i listan) som det borde.
Har någon en ledtråd om vad jag saknar?
logs.component.html
<div class="logContent">
<div class="row">
<div class="col-12" *ngFor="let log of this.logService.getLogs()">
<app-singlelog [when]="log.when" [type]="log.type" [data]="log.data"></app-singlelog>
</div>
</div>
</div>
log.service.ts
export class LogService {
private logArray = [];
/* private logObject = {} as Log; */
constructor(private httpservice: HttpserviceService) {
}
public getLogs(): Array<Log> {
this.httpservice.getLogs().subscribe(data => {
data.forEach(index => {
let logObject = {} as Log;
logObject.when = index.when;
logObject.type = index.type;
logObject.data = index.data;
this.logArray.push(logObject);
})
}
)
return this.logArray;
}
}
Tack :)
Svar #1
Använd inte funktionsanrop från HTML-mallen för att visa data.
Anropa istället getLogs()-funktionen från Angulars ngOnInit()-funktion och lagra svaret i en variabel. Loopa sedan på den variabeln:
export class LogService implements OnInit {
// ...
logs = [];
ngOnInit() {
this.getLogs();
}
getLogs(): Array<Log> {
this.httpservice.getLogs().subscribe(data => {
data.forEach(index => {
let logObject = {} as Log;
logObject.when = index.when;
logObject.type = index.type;
logObject.data = index.data;
this.logArray.push(logObject);
});
// assign the variable here:
this.logs = data;
});
}
I mallen:
<div class="col-12" *ngFor="let log of logs">
<app-singlelog [when]="log.when" [type]="log.type" [data]="log.data"></app-singlelog>
</div>
Anledningen bakom detta är det faktum att Angular anropar din getLogs-funktion vid varje sidrenderingscykel. Men du bör bara anropa HTTP-förfrågan en gång, när du initierar komponenten.
Glöm inte att avanmäla dig från din Observable. ;) - korrigerad från kommentaren nedan.
Svar #2
Du kan också använda den reaktiva metoden och göra följande:
Definiera den observerbara en gång i din komponent:
logs$ = this.httpservice
.getLogs()
.pipe(
shareReplay(),
map((data) => data.map(({ when, type, data }) => ({ when, type, data })))
);
Inkludera följande i din komponent-HTML:
<div class="col-12" *ngFor="let log of logs$ | async">
<app-singlelog [when]="log.when" [type]="log.type" [data]="log.data"></app-singlelog>
</div>
