【问题标题】:How to dynamically change the bound formControlName如何动态更改绑定的formControlName
【发布时间】:2017-07-12 08:10:54
【问题描述】:

我有一个 angular 2 反应形式,有四个 formControls,只有一个输入字段。我想要的是要求用户一一填写信息。因此,我将firstControlName 分配给ngOnInit 上的属性调用currentFormControlName,并将其与模板文件中的输入字段绑定。当用户填写他的姓名时,该字段将有效并且在提交时我会将currentFormControlName 属性更改为下一个formControlName。但问题是绑定没有更新。输入字段仍然绑定到name。当我在输入字段中输入内容时,name 的值正在更新,而不是 email

app.component.ts

ngOnInit() {
  this.form = this.builder.group({
    'name': ['', Validator.required],
    'email': ['', Validator.email],
    'phone': ['', Validator.required],
    'password': ['', Validator.required],
  });
  this.currentFormControlName = 'name';
}

submit() {
  this.currentFormControlName = 'email'; // Setting it manually just for the demo of this question.
}

app.component.html

<form [formGroup]="form">
  <input type="text" [formControlName]="currentFormControlName">
  <input type="submit" (click)="submit()">
</form>

【问题讨论】:

  • 你尝试过this.currentFormControlName = this.form.get('name');(并且对邮件使用相同的方法)?
  • 我不认为这是可能的..每个输入都需要有一个表单控件女巫在表单组的初始化中定义。
  • 您可以将 ngSwitch 与 Subject 结合使用,并且每次触发 submit() 时,您都会通过显示 nexy 输入字段来更新表单

标签: angular angular-reactive-forms


【解决方案1】:

更新

你也可以使用FormControlDirective来切换控件

[formControl]="form.get(currentFormControlName)"

旧答案

假设我们有以下内容

template.html

<form [formGroup]="form" #formDir="ngForm">
    <input type="text" #controlDir [formControlName]="currentFormControlName">
    <input type="submit" (click)="submit()">
</form>
<pre>{{ form.value | json }}</pre>

点击提交按钮后,我们可以更改currentFormControlName并使用新名称注册控件

component.ts

form: FormGroup;

@ViewChild('formDir') formDir: FormGroupDirective;
@ViewChild('controlDir', { read: FormControlName }) controlDir: FormControlName;

currentFormControlName: string;

constructor(private builder: FormBuilder) {}

ngOnInit() {
    this.form = this.builder.group({
        'name': ['', Validators.required],
        'email': ['', Validators.email],
        'phone': ['', Validators.required],
        'password': ['', Validators.required],
    });
    this.currentFormControlName = 'name';
}

submit() {
    this.formDir.removeControl(this.controlDir);
    this.controlDir.name = this.currentFormControlName = 'email'
    this.formDir.addControl(this.controlDir);
}

之后我们的输入元素将管理email 值。因此,如果我们在input 中输入一些内容,它将反映在form.email 值中

Plunker Example

本方案基于FormControlName source code

ngOnChanges(changes: SimpleChanges) {
  if (!this._added) this._setUpControl();
  if (isPropertyUpdated(changes, this.viewModel)) {
    this.viewModel = this.model;
    this.formDirective.updateModel(this, this.model);
  }
}

我们可以看到这个指令只注册一次控制。但它也有以下 ngOnDestroy 钩子

ngOnDestroy(): void {
  if (this.formDirective) {
    this.formDirective.removeControl(this);
  }
}

这给了我一些想法

Plunker Example

【讨论】:

    【解决方案2】:

    ngFormNameDirective

    你不能这样做,因为ngFormControlName 指令在这里只使用了一次@Input() name

    @Directive({selector: '[formControlName]'...})
    export class FormControlName extends ... {
      @Input('formControlName') name: string;
    
      ngOnChanges(changes: SimpleChanges) {
        if (!this._added) this._setUpControl(); <------------ here
        if (isPropertyUpdated(changes, this.viewModel)) {
    

    在每个后续更改中,this._added 将变为 true。您可以在ngOnChanges 中看到的下一个检查是isPropertyUpdated,它不检查name 输入更改,只检查model 输入:

    export function isPropertyUpdated(changes: {[key: string]: any}, viewModel: any): boolean {
      if (!changes.hasOwnProperty('model')) return false;
      const change = changes['model'];
    

    ngFormDirective

    要执行您想要执行的操作,您需要使用 ngFormDirective 来检查控件是否已更新:

    export class FormControlDirective extends NgControl implements OnChanges {
      viewModel: any;
    
      @Input('formControl') form: FormControl;
    
      ngOnChanges(changes: SimpleChanges): void {
        if (this._isControlChanged(changes)) {
    
      private _isControlChanged(changes: {[key: string]: any}): boolean {
        return changes.hasOwnProperty('form');
      }
    

    但是,这是一个独立的指令。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 2016-08-04
      • 1970-01-01
      • 2020-01-03
      相关资源
      最近更新 更多