使用查询参数初始化模板驱动的表单

Sta*_*avm 5 angular angular-forms

我想用查询参数值初始化模板驱动的表单

直观地,您将创建表单并填充它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>
Run Code Online (Sandbox Code Playgroud)

成分:

@ViewChild('f') f: NgForm;

constructor(private route: ActivatedRoute) {}
  
ngAfterViewInit() {
    const queryParams = this.route.snapshot.queryParams;

    this.f.form.setValue(queryParams)
}
Run Code Online (Sandbox Code Playgroud)

然后使用查询参数访问它: ?fname=aaa&lname=bbb

现在,这种方法有两个问题:

  1. 事实证明,这不起作用,因为 Angular 需要另一个勾号来注册表单
  2. setValue将不起作用,因为第二个 ctrllname在应用值时不存在。

这将需要我

  1. 添加一个额外的周期(Angular 团队建议 setTimeout @ 控制台错误)
  2. 使用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))
  }
Run Code Online (Sandbox Code Playgroud)

有没有做到这一点少哈克的方式没有对元器件面的每个控制创建变量这样做,会,在我看来,化妆模板驱动的冗余。

附:stackblitz 演示的“hacky”soultion

abh*_*thi 0

我们可以[(ngmodel)]与局部变量一起使用直接绑定到这里。

<form #f="ngForm">
    <input type="text" id="firstName" name="fname" #fname [(ngModel)]="myfname">
    <input *ngIf="fname.value" type="text" id="lastName" name="lname" [(ngModel)]="mylname">
    <button type="submit">Submit</button>
</form>
Run Code Online (Sandbox Code Playgroud)

一些组件.ts

myfname:string;
mylname:string;

ngAfterViewInit() {
    const queryParams = this.route.snapshot.queryParams;
    myfname = queryParams.fname;
    mylname = queryParams.lname;
}
Run Code Online (Sandbox Code Playgroud)

我们也可以使用constructor()来代替ngAfterViewInit().