【发布时间】:2020-08-11 06:28:51
【问题描述】:
我想用查询参数值初始化一个模板驱动表单。
您可以直观地创建表单并将其填充到ngAfterViewInit:
HTML
<form #f="ngForm">
<input type="text" id="firstName" name="fname" #fname ngModel>
<input *ngIf="fname.value" type="text" id="lastName" name="lname" ngModel>
<button type="submit">Submit</button>
</form>
组件:
@ViewChild('f') f: NgForm;
constructor(private route: ActivatedRoute) {}
ngAfterViewInit() {
const queryParams = this.route.snapshot.queryParams;
this.f.form.setValue(queryParams)
}
然后使用查询参数访问它:?fname=aaa&lname=bbb
现在,这种方法有两个问题:
- 事实证明,这不起作用,因为 Angular 需要 another tick to register the form
-
setValue不起作用,因为第二个 ctrllname在应用值时不存在。
这需要我去
- 添加一个额外的循环(Angular 团队建议 setTimeout @ 控制台错误)
- 使用只应用有效值的
patchValue,两次。
类似:
ngAfterViewInit() {
const queryParams = { fname: 'aaa', lname: 'bbb'};
// if we wish to access template driven form, we need to wait an extra tick for form registration.
// angular suggests using setTimeout or such - switched it to timer operator instead.
timer(1)
// since last name ctrl is only shown when first name has value (*ngIf="fname.value"),
// patchValue won't patch it on the first 'run' because it doesnt exist yet.
// so we need to do it twice.
.pipe(repeat(2))
// we use patchValue and not setValue because of the above reason.
// setValue applies the whole value, while patch only applies controls that exists on the form.
// and since, last name doesnt exist at first, it requires us to use patch. twice.
.subscribe(() => this.f.form.patchValue(queryParams))
}
有没有更简单的方法来实现这一点不为组件端的每个控件创建一个变量,在我看来,这样做会使模板驱动变得多余。
附:stackblitz Demo 的“hacky”灵魂
【问题讨论】:
-
模板驱动表单使用 [(ngModel)],我在你的代码中看不到
标签: angular angular-forms