Hi everyone. I want to asynchronously populate a dynamic form array, showed in this example:
import { Component, signal } from '@angular/core';
import { Observable, of } from 'rxjs';
import { delay, finalize } from 'rxjs/operators';
import { OnInit, Injectable, inject, effect } from '@angular/core';
import { ReactiveFormsModule, FormBuilder, FormControl } from '@angular/forms';
@Component({
selector: 'app-root',
imports: [ReactiveFormsModule],
template: `
<div class="h-screen flex flex-col items-center justify-center space-y-2">
@for(control of form.controls; track $index) {
<label>Name:
<input type="text" [formControl]="control" class="border border-gray-400 rounded-sm ms-2"/>
</label>
}
</div>
`
})
export class App implements OnInit {
private store = inject(MailStore);
private fb = inject(FormBuilder);
protected form = this.fb.array<FormControl<string | null>>([]);
constructor() {
effect(() => {
const attachments = this.store.attachments();
if (attachments == null) return;
attachments.forEach(att => this.form.push(new FormControl(att)));
});
}
ngOnInit() {
this.store.loadAttachments();
}
}
@Injectable({providedIn: "root"})
export class MailStore {
attachments = signal<string[] | null>(null);
loadAttachments(): void {
this.getAttachments().subscribe({
next: value => this.attachments.set(value)
});
}
getAttachments(): Observable<string[]> {
return of(["Attachment 1", "Attachment 2", "Attachment 3"])
.pipe(delay(2400));
}
}
But I get the error:
ERROR RuntimeError: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: '[object Object]'
How to populate a form array with data from an asynchronous source?