【问题标题】:How can we get form value in Angular as object with multiple properties?我们如何在 Angular 中获取表单值作为具有多个属性的对象?
【发布时间】:2021-11-08 00:23:09
【问题描述】:

我有一个对象数组:

arr = [{
    "name": "firstName",
    "type": "text",
    "required": false
  },
  {
    "name": "lastName",
    "type": "text",
    "required": false
  },
    {
    "name": "dob",
    "type": "date",
    "required": false
  }
]

我正在使用 *ngFor 和 formControlName 在 HTML 中创建一个表单,如下所示:

createFormgroup() {
  arr.forEach((control: any) => {
    this.createFormGroup.addControl(
      control.name,
      this.fb.control(false)
    );
    this.createFormGroup.addControl(
      "required" + i,
      this.fb.control(false)
    );
  });
}

submit(form: NgForm) {
  console.log(form.value)
}
<mat-label>Enter form name:</mat-label>
<input class="form-name-input" matInput placeholder="Form Name" formControlName="formName" required>

<form [formGroup]="createFormGroup" (ngSubmit)="submit(createFormGroup)">
  <div *ngFor="let a of arr; let i = index">
    <mat-checkbox formControlName="{{a.name}}">{{ a.name }}</mat-checkbox>
    <mat-checkbox formControlName="required{{i}}">required</mat-checkbox>
  </div>
  <button type="submit">submit</button>
</form>

在这里,我试图实现将值显示和发布为一个相对于另一个的对象。例如,如果我检查 HTML 中的名字、dob 和所需的,当单击 submit() 时,我想要整个对象。 点击 submit() 时,我正在寻找如下输出:

form.value = [{
  "name": "firstname",
  "type": "text",
  required: true
}, {
  "name": "dob",
  "type": "date",
  required: false
}]

我对如何实现这一点感到困惑。有办法吗?此外,我需要为每个必填字段分配不同的 formControl 名称。我不知道该怎么做。

我附上一张图片以供理解。 UI image

注意:我知道如何从表单中获取值,但我正在寻找一种方法来复制整个对象

为简单起见:我需要用于创建表单的相同数组,最后我需要根据用户输入更改相同对象属性的相同数组

【问题讨论】:

  • 对于必填字段的formControlName,我知道我可以对所有内容使用索引。但是,有没有其他不使用索引的方法呢?
  • 你试过createFormGroup.value吗?
  • @AmerYousuf 是的,它将表单对象返回为 { "firstName": true, "lastName": false, "dateOfBirth": false, required0: true }。我需要它作为一个对象,并将相应的属性添加到同一个对象。
  • 所以您需要与创建表单时相同的数组吗?
  • @NavnathJadhav 太好了。这就是我要找的。我想我没有使用简单的词就把它复杂化了。

标签: javascript arrays angular typescript reactive-forms


【解决方案1】:

您可以通过以下方式实现:

  • 为源数组中的每个项目定义一个子表单组,并将其添加到主formGroup
  • 为名称复选框添加 change 事件处理程序,以禁用/启用子表单组,从值中排除(在 Angular 中,如果禁用表单控件或子表单组那么它的值将从 FormGroup.value 中排除)
  • 循环遍历组件模板中的表单数组,并仅绑定到required 表单控件。

所以组件类将如下所示:

ngOnInit() {
  this.formGroup = this.fb.group({
    formName: null,
    arrForm: this.fb.array(this.createSubFormGroup())
  });
}

createSubFormGroup() {
  return this.arr.map(
    (control: { name: string; type: string; required: boolean }) => {
      const subForm = this.fb.group({
        name: control.name,
        type: control.type,
        required: control.required
      });

      // disable by default to be not included with the value until it's checked.
      subForm.disable();

      return subForm;
    }
  );
}

/** To enable/disable the sub formGroup if the checkbox checked/unchecked */
onNameCheckChange(ndx: number, event: MatCheckboxChange) {
  (this.formGroup.get('arrForm') as FormArray).controls[ndx][event.checked ? 'enable' : 'disable']();
}

submit() {
  console.log(this.formGroup.value?.arrForm || []);
}

组件模板如下所示:

<form [formGroup]="formGroup" (ngSubmit)="submit()">
  <mat-label>Enter form name:</mat-label>
  <input class="form-name-input" matInput placeholder="Form Name" formControlName="formName" required>

  <div formArrayName="arrForm">
    <div *ngFor="let a of arr; let i = index" [formGroupName]="i">
      <mat-checkbox (change)="onNameCheckChange(i, $event)">{{ a.name }}</mat-checkbox>
      <mat-checkbox formControlName="required">required</mat-checkbox>
    </div>
  </div>
  <button type="submit">submit</button>
</form>

这是工作的StackBiltz

【讨论】:

    【解决方案2】:

    第一次更改:

    this.createFormGroup.addControl(
      "required" + i,
      this.fb.control(false)
    );
    

    this.createFormGroup.addControl(
      "required_" + control.name,
      this.fb.control(false)
    );
    

    // your current result
     const obj =  {
     'firstName': true,
     'required_firstName': true,
     'lastName': true,
     'required_lastName': false,
     'dob': true,
     'required_dob': true
    };
     
     // your array
    const arr = [
        {
            name: "firstName",
            type: "text",
            required: false
        },
        {
            name: "lastName",
            type: "text",
            required: false
        },
        {
            name: "dob",
            type: "date",
            required: false
        }
    ];
    
    const validKeys = Object.keys(obj).filter(key => obj[key] && (key.split("_").length==1));
    
    // your required output
    const finalResult = arr.filter(item => validKeys.includes(item.name)).map(item => ({...item, required: obj['required_'+item.name]}));
    
    console.log(finalResult);

    【讨论】:

      猜你喜欢
      • 2016-08-03
      • 2017-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-14
      • 1970-01-01
      相关资源
      最近更新 更多