如何填充在Angular反应性表单中提交的选择表单?

时间:2019-04-15 17:01:15

标签: angular angular-reactive-forms

我正在尝试填充通过HTTP调用提交的选择表单。我得到了数据,但似乎无法使用FormArray正确设置值。

我尝试调整对象的call.references甚至使用数组表示法。我可以将其转储到控制台,但不能填充选择表单字段。因此,我认为我的Angular代码中有错误,但是在网上找到该示例的失败。我遇到的所有文档/教程在表单中都没有选择内容。

public ngOnInit () {
    // Reactive form fields
    this.timecardForm = this.fb.group( {
      payBeginningDate: [ '2019-03-19', [ Validators.required ] ],
      payEndingDate: [ '2019-03-26', [ Validators.required ] ],
      payCategoriesTracked: this.fb.array( [ this.buildPayCategoriesTracked() ] ), // This is the one on which I am working
      overtimeCategories: '1',
      workHoursTracked: this.fb.array( [ this.buildWorkTracked() ] ),
      earnings: [ { value: null, disabled: true }, [ Validators.required ] ],
      totalHours: [ { value: null, disabled: true }, [ Validators.required ] ],
      totalEarnings: [ { value: null, disabled: true }, [ Validators.required ] ]
    } );
... // There is some more unrelated code
// Dynamically build payCategories row
  buildPayCategoriesTracked (): FormGroup {
    console.log( 'buildPayCategoriesTracked: ', this.timeEntry.payCategories ); // This prints to the console successfully
    return this.fb.group( {
      payCategories: [ this.timeEntry.payCategories, [ Validators.required ] ]
    } );
  }
<!-- The HTML in question... -->
<select formControlName="{{i}}"
        id="{{ 'payCategoriesTracked' + i }}"
        class="form-control"
        (change)="onRecordUpdated(timeCard, timecardDet)"
        [ngClass]="{'is-invalid': payCategoriesMessage }">
        <option value=null
                disabled
                selected
                hidden>--Select--</option>
        <option *ngFor="let payCategory of payCategories"
        [ngValue]="payCategoryDescription.payCategoryId">{{payCategoryDescription}}</option>
        </select>

我只希望我的payCategories填充我的选择表单字段。返回的一项示例为:

{payCategoryId:9,说明:“ DUE FROM LIBRAR”,payType:“ Hourly”,isActive:true}

所以我希望选择值是id,并在选项标签中显示说明。

更新 我已经按如下方式更改了HTML ...

<div *ngFor="let payCategoriesTracked of payCategoriesTracked.controls;let i=index">
<mat-form-field>
    <mat-label>Pay Category</mat-label>
    <mat-select formControlName="i"
                (change)="onRecordUpdated(timeCard, timecardDet)"
                [ngClass]="{'is-invalid': payCategoriesMessage }">
        <mat-option *ngFor="let payCategory of payCategories"
                    [ngValue]="payCategory.value">
            {{payCategory.description}}
        </mat-option>
    </mat-select>
</mat-form-field>

解决方案 我想通了...哇! 这是我的解决方法...

<mat-form-field>
    <mat-label>Pay Category</mat-label>
    <select matNativeControl
            formControlName="payCategory">
        <option *ngFor="let payCategory of payCategories"
                [ngValue]="payCategory">
          {{payCategory.description}}
        </option>
    </select>
</mat-form-field>
// This is the FormControl, which is within a formgroup...
payCategory: new FormControl( this.buildPayCategories() )
// Pull in payCategories for select list from service
  buildPayCategories () {
    this.payCategories = this.timeEntry.payCategories;
    return this.payCategories;
  }

2 个答案:

答案 0 :(得分:0)

使用ngFor在模板中使用“ this.timeEntry.payCategories”构建选项

<option *ngFor="let payCategory of timeEntry.payCategories" [value]="payCategory.payCategoryId">{{ payCategory.description }}</option>

在构建反应式表单时,FormControl中的第一个参数应该是select中的值,换句话说,selected选项中的值。示例:

return this.fb.group( {
      payCategories: [ 2, [ Validators.required ] ]
    } );

将匹配等于2的选项。

答案 1 :(得分:0)

黏土,如果需要FormGroup的FormArray或FormControls的FormArray,则需要选择。

FormGroups的FormArray

  myForm=new FormGroup({
    myArray:new FormArray([
    new FormGroup({
      prop1:new FormControl('',Validators.required),
      prop2:new FormControl('',Validators.required)
    })
  ])
  })

<!--your form--->
<form [formGroup]="myForm">
    <!--a div with formArrayName--->
    <div formArrayName="myArray">
        <!--a div that iterate over "controls" and has [formGroupName]-->
        <div *ngFor="let group of myForm.get('myArray').controls;
                  let i=index" [formGroupName]="i">
            <!--your input using formControlName-->
            <input formControlName="prop1">
            <input formControlName="prop2"/>
         </div>
    </div>
</form>
{{myForm?.value|json}}
//Some like { "myArray": [ { "prop1": "", "prop2": "" } ] } 

FormControls的FormArray

  myForm2 = new FormGroup({
    myArray: new FormArray([
      new FormControl('', Validators.required),
      new FormControl('', Validators.required)
    ])
  })

<!--your form--->
<form [formGroup]="myForm2">
    <!--a div with formArrayName--->
  <div formArrayName="myArray">
  <!--a div that iterate over "controls"-->
  <div *ngFor="let group of myForm2.get('myArray').controls;let i=index">
      <!--a unique element using [formControlName]-->
      <input [formControlName]="i">
  </div>
  </div>
</form>
{{myForm2?.value|json}}
//will be like  { "myArray": [ "", "" ] }

注意:我直接使用new FormGroup和new FormArray,而不是FormBuilder。这样就避免了注入FormBuilder的麻烦,并且,如果需要,可以更改“更改检测”,但是在sintax中,差别不大

注2:在数组中引用控件的方式更多,但我认为这是最重要的。

制作表单的提示

  1. 始终以{{form?.value | json}}开头。一个formGroup存在 “输入”的独立性
  2. 我们开始写<form *ngIf="form" [formGroup]="myForm"></form>
  3. 首先使用简单的输入
  4. 总是需要知道我们要在form.value中获得什么

更新关于选择。选择是输入,只需将formControlName赋予“选择”即可。选择需要一个对象数组来显示选项。 如果我们的对象数组具有两个属性,即“值”和“文本”,则通常使用类似以下内容的

//If our arrayForm is an ArrayForm of FormGroups
<select formControlName="prop1">
  <options *ngFor="let item of options" [value]="item.value">
      {{item.text}}
  </option> 
</select>
//If our arrayForm is a Array of FormControls
<select [formControlName]="i">
  <options *ngFor="let item of options" [value]="item.value">
      {{item.text}}
  </option> 
</select>

首先,考虑到在任何地方都没有[选定的]:这不是必需的。如果我们可以选择一个值,那么我们将为FormControl赋值。

当我们使用ReactiveForm时,通常尽管使用(更改),我们仍然订阅控件的changeValue属性,并且我们必须谨慎:在选项中,我们可以使用[value]或[ngValue]。但是值可以是简单变量(字符串或数字)或复杂对象。如果我们不使用Cascate中的dropdop,那么通常只使用一个简单变量。

更新 我进行了更改,我想我已经接近了,因为我看到了通过{{timecardForm?.value | json}}

转储到屏幕上的数据

我收到control.registerOnChange不是函数错误,这使我相信我引用了不正确的内容。这是我更新的代码...

<div class="col-2">
          <div formArrayName="payCategoriesTracked">
            <div *ngFor="let payCategory of payCategoriesTracked.controls; let i=index">
              <mat-form-field>
                <mat-label>Pay Category</mat-label>
                <mat-select [formControlName]="i"
                            (change)="onRecordUpdated(timeCard, timecardDet)"
                            [ngClass]="{'is-invalid': payCategoriesMessage }">
                  <mat-option *ngFor="let payCategory of payCategories"
                              [ngValue]="payCategory">
                    {{payCategory.description}}
                  </mat-option>
                </mat-select>
              </mat-form-field>
            </div>
          </div>

数据转储如下...

“ payCategoriesTracked”:[{“ payCategories”:[{“ payCategoryId”:1,“ description”:“ Converted Data”,...等。