1

我有一个功能,我需要在单击按钮时发送动态生成的输入字段。

为了更好地理解,我在stackblitz上重新创建了这个问题。

在该应用程序中,当我输入 resourceQuantity 时,会动态生成 resourceId 字段。我的问题是单独识别这些字段并通过单击按钮将它们发送到服务器端。

我在 stackblitz 上找到的这个解决方案是相似的,但在我的问题中,我不是删除或添加按钮点击,而是(更改)事件。

这是HTML代码:

<mat-form-field>
    <input  matInput type="number" formControlName="resourceQuantity" [(ngModel)]="resourceQuantity" placeholder="Enter Resource Quantity" (change)="somethingChanged()"/> 
</mat-form-field><br/><br/>
<div>
    <ul>
        <li *ngFor="let item of counter(resourceQuantity)">
            <input  matInput type="number" placeholder="Enter Resource Number" formControlName="resourceId"/> 
        </li>       
    </ul>
</div>

这是TS代码:

  ngOnInit() {
    this.form = new FormGroup({
            'employeeId': new FormControl(null, {validators: [Validators.required]}),
            'employeeName': new FormControl(null, {validators: [Validators.required]}),
            'resourceQuantity': new FormControl(null, {validators: [Validators.required]}),
            'resourceId': new FormControl(null, {validators: [Validators.required]})
    });
  }

  somethingChanged() {
      console.log(this.resourceQuantity);
  }

  counter(i: number) {
      return new Array(i);
  }

请让我知道我的问题的最佳解决方案。谢谢。

4

4 回答 4

2

避免ngModelformControl一起使用。您可以使用formArray组件中的 getter 函数来获取结果。

Edit: I have edited my code to reflect the change you requested by subscribing to valueChanges on the resourceQuantity formControl and generating the formArray when it detects the change. This creates the resources in real time.

Note: Don't forget to unsubscribe from valueChanges to prevent memory leakage. I have updated my Stackblitz to show the same.

Here is a working example on StackBlitz

于 2019-07-05T06:13:57.003 回答
1

您在这里拥有的是一个完美的用例formArray……唯一的区别是您需要根据在resourceQuantity字段中输入的值添加 formControls。

相关的 HTML

<mat-card>
    <form [formGroup]="form" (submit)="add()">
        <mat-form-field>
            <input matInput type="number" formControlName="employeeId" placeholder="Enter Employee Id" (change)='updateFormString()'/>
      </mat-form-field><br/><br/>
      <mat-form-field>
            <input matInput formControlName="employeeName" placeholder="Enter Employee Name" (change)='updateFormString()'/>
      </mat-form-field><br/><br/>
      <mat-form-field>
            <input  matInput type="number" formControlName="resourceQuantity" [(ngModel)]="resourceQuantity" placeholder="Enter Resource Quantity" (change)="somethingChanged()"/> 
        </mat-form-field><br/><br/>
           <!--
             <div>
                <ul>
                    <li *ngFor="let item of counter(resourceQuantity)">
                        <input  matInput type="number" placeholder="Enter Resource Number" formControlName="resourceId"/> 
                    </li>       
                </ul>
            </div>
            -->
        <div fxLayout>
            <div>
                <button
                    mat-raised-button
                    color="accent" [disabled] = "form.invalid">Save
                </button>
            </div>
        </div>

        <div formArrayName='resourceId'>
          <br/>
          <div *ngFor='let item of resourceId.controls; let i = index'>
            <input type='text' [formControlName]="i" >
          </div>
        </div>

    </form>
</mat-card>

{{formString}}

相关TS

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators, FormArray, FormBuilder } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  form: FormGroup;
  resourceQuantity: any;
  formString: string;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.form = this.fb.group({
      'employeeId': new FormControl(null, { validators: [Validators.required] }),
      'employeeName': new FormControl(null, { validators: [Validators.required] }),
      'resourceQuantity': new FormControl(null, { validators: [Validators.required] }),
      //'resourceId': new FormControl(null, {validators: [Validators.required]}),
      resourceId: this.fb.array([
        this.fb.control('test entry default')
      ])
    });
  }

  updateFormString() {
    this.formString = JSON.stringify(this.form.value);
  }

  somethingChanged() {
    for (var i = 1; i < this.resourceQuantity; i++) {
      this.addResource();
    }
    this.updateFormString();
  }

  get resourceId() {
    return this.form.get('resourceId') as FormArray;
  }

  addResource() {
    this.resourceId.push(this.fb.control('test entry additional'));
  }

  counter(i: number) {
    return new Array(i);
  }
}

可在此处使用 stackblitz

于 2019-07-05T06:01:15.693 回答
1

你应该用它FormArray来解决这个问题。StackBlitz 演示

1.将您的resourceIdFormControl更改FormArray为如下。

 'resourceId': new FormArray([])

2.根据Resource Quantity改变你的counter推入方法FormControl,这个方法在Resource Quantity中触发change事件时调用。它从 中获取值,然后清除该值。之后,它循环遍历索引以动态创建并推送它FormArrayresourceQuantityFormGroupFormArrayFormControlFormArray

counter() {
    const index = parseInt(this.form.value.resourceQuantity);
    (this.form.controls.resourceId as FormArray).clear();
    for(let i = 0; i < index; i++) {
      const formControl = new FormControl();
      (this.form.controls.resourceId as FormArray).push(formControl);
    }
}

3.使用getter轻松访问控件

  get formControls(): any {
    return this.form.controls;
  }

  get resourceIDControls(): any {
    return this.form.controls.resourceId['controls'];
  }

4.改变你的HTML循环FormArrayFormControlName动态设置。

<div formArrayName="resourceId">
     <ul>
         <li *ngFor="let item of resourceIDControls; let i = index">
             <input  matInput type="number" placeholder="Enter Resource Number" [formControlName]="i"/> 
         </li>       
     </ul>
 </div>

Sample Inputs - Demo

Form Value after the submission will look like this

于 2019-07-05T06:12:02.887 回答
1

I would also set up my employee model to include a Resource array;

import { Resource } from './resource.model';

export interface Employee {
    employeeId: number;
    employeeName: string;
    resourceQuantity: number;
    resourceIds: Resource[];
}

Then your resource just needs a id:

export interface Resource {
    resourceId: number;
}
于 2019-07-05T06:16:02.130 回答