使用反应形式并在推送时更改检测。
我一直在寻找如何做这个例子我觉得这很常见,但是,我似乎找不到如何正确地做这个的好例子。
当尝试在ngOnInit内更新包含订阅内部FormGroup列表的FormArray时,FormArray对象会更新,但除非在组件上强制进行更改检测,否则视图不会更新FormArray组。以这种方式更新的所有其他控件都在工作。所以感觉好像我尝试更新FormArray是错误的,我不应该也不想强制更改检测。
import { Component, OnInit, ChangeDetectionStrategy } from "@angular/core";
import { JournalTransactionService } from "app/accounting/shared-services/journal-transaction.service";
import { JournalEntry } from "accountingModels";
import { FormBuilder, FormGroup, FormArray } from "@angular/forms";
import { EntryLine } from "app/accounting/models/journal";
@Component({
selector: "general-journal",
templateUrl: "./general-journal.component.html",
styleUrls: ["./general-journal.component.scss"],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class GeneralJournalComponent implements OnInit {
journalEntry: JournalEntry;
journalEntryForm: FormGroup;
constructor(private _journalTransactionService: JournalTransactionService, private _formBuilder: FormBuilder) { }
get entryLines(): FormArray {
return <FormArray>this.journalEntryForm.get("entryLines");
};
ngOnInit() {
this.journalEntryForm = this._formBuilder.group(
{
transactionId: "",
transactionDate: "",
autoReversalDate: "",
journalEntryType: "",
entryLines: this._formBuilder.array([])
}
);
this._journalTransactionService.getTransaction("", 80).subscribe(journalEntry => {
journalEntry.entryLines.forEach(entryLine => {
this.entryLines.push(this.entryLineMapper(entryLine));
});
this.journalEntryForm.patchValue(
{
transactionId: journalEntry.transactionId,
transactionDate: journalEntry.transactionDate,
autoReversalDate: journalEntry.autoReversalDate,
journalEntryType: journalEntry.journalEntryType
}
);
});
}
private entryLineMapper = (entryLine: EntryLine): FormGroup => {
return this._formBuilder.group({
accountId: entryLine.accountId,
controlId: entryLine.controlId,
debit: entryLine.debit,
credit: entryLine.credit,
description: entryLine.description,
})
}
}
html的相关部分。如果键入任何其他绑定字段(如事务ID),则运行更改检测并填写表。如果您在订阅块中的补丁值之后手动触发更改检测,则表格将被填写。
<tbody formArrayName="entryLines">
<tr *ngFor="let entryLine of entryLines.controls; index as i" [formGroupName]="i">
<td>
<input type="text" class="form-control" formControlName="accountId">
</td>
<td>
<input type="text" class="form-control" formControlName="controlId">
</td>
<td>
<input type="text" class="form-control" formControlName="debit">
</td>
<td>
<input type="text" class="form-control" formControlName="credit">
</td>
<td>
<input type="text" class="form-control" formControlName="description">
</td>
</tr>
</tbody>
更新
为了解决这个问题,我现在要创建两个组件,一个是功能的基本组件,另一个是包装表单。这允许我传递用于构建表单的数据作为表单组件的输入,从而允许OnPush检测工作。我对此感到满意,但仍然感觉FormArray应该能够通过订阅添加FormGroups或控件,并在UI中更新新值。我认为如果FormArray控件是AbstracControl的可观察对象,这将起作用。如果有人有更好的解决方案,请让我们都知道。
答案 0 :(得分:0)
请勿使用map
而只使用push
。
private entryLineBuilder = (entryLines: EntryLine[]): FormArray => {
return this._formBuilder.array(entryLines.push(this.entryLineMapper));
}
因为您正在通过推动来更改阵列,这反过来会触发角度变化检测。
答案 1 :(得分:0)
不确定是否找到答案。使用removeAt
将触发Angular 8中的更改检测。