【问题标题】:dynamic mat-checkbox not displaying from FormGroup动态 mat-checkbox 未从 FormGroup 显示
【发布时间】:2019-03-26 05:30:13
【问题描述】:

我希望从数组中填充 mat-checkboxes。我能够构建表单组和表单数组并在控制台中查看它们的内容。但我无法使用 ngFor 获取要显示的设备列表。我查找了多个响应式表单的示例,并认为我正确地执行了这个 html,但显然我遗漏了一些东西。

这里是ts代码:

import { Aircraft } from '../../shared/aircraft';
import { Component, OnInit, Inject } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material";
import { ViewEncapsulation } from '@angular/core';
import { forEach } from '@angular/router/src/utils/collection';

interface IAircraftCheckbox {
  imei: string;
  selected: boolean;
  name: string;
}

@Component({
  selector: 'app-historical-track-dialog',
  templateUrl: './historical-track-dialog.component.html',
  styleUrls: ['./historical-track-dialog.component.scss',],
  encapsulation: ViewEncapsulation.None
})


export class HistoricalTrackDialogComponent implements OnInit {
aircraftData: any[];
imeiToTrack: string[];
breakpoint: number;
form: FormGroup;
aircraftArray: FormArray;
allSelected: boolean;

  constructor(public dialogRef: MatDialogRef<HistoricalTrackDialogComponent>,
              private fb: FormBuilder,
              @Inject(MAT_DIALOG_DATA) public data: Aircraft[]) {
    this.aircraftData = data;
    console.log('historical track dialog, this.aircraftList: ', data);
    this.aircraftArray = new FormArray([new FormControl('CAP')]);
    this.aircraftArray = this.mapAircraftToCheckboxArrayGroup( this.aircraftData);
    this.form = new FormGroup({
      aircraftList: this.aircraftArray
    });
    this.allSelected = false;
    console.log('this.form: ', this.form);
    console.log('this.aircraftList = ', this.form.controls.aircraftList);
  }

  mapAircraftToCheckboxArrayGroup( aircraft: Aircraft[]): FormArray {
    return this.fb.array(aircraft.map((i) => {
      return this.fb.group ({
        imei: i.IMEI,
        selected: false,
        name: i.DeviceName
      });
    }));
  }

  checkboxToggle(e) {
    console.log('CheckboxToggle, e=', e);
    console.log('source.id', e.source.id);
    console.log('status: ', e.checked);
  }

  toggleAll(e) {
    for (const control of this.aircraftArray.controls) {
      if (this.allSelected === true ) {
        console.log('setting ', control.value.name, 'to false');
        control.value.selected = false;
      } else {
        control.value.selected = true;
        console.log('setting ', control.value.name, 'to true');
      }
    }
    this.allSelected = this.allSelected === true ? false : true;
    this.form.markAsDirty();

  }
  ngOnInit() {
this.breakpoint = (window.innerWidth <= 690) ? 1 : 4;
  }
  onResize(event) {
    this.breakpoint = (event.target.innerWidth <= 690) ? 1 : 4;
  }

  close() {
    console.log('close, formArray: ', this.aircraftArray.controls);
    for (const control of this.aircraftArray.controls) {
      if (control.value.selected === true ) {
        console.log('aircraft checked: ', control.value.name);
      }
    }
    this.dialogRef.close();

  }

}

这里是html:

<div class="aList-container"
      fxLayout="column"
      fxLayoutGap="10px"
      fxLayoutAlign="start"
       style="width:500px;max-height:50%">

      <div >
          <div class="a-list-title" >
            <h3>AIRCRAFT LIST</h3>
            <hr>
          </div>
      </div>

      <div class="checkboxList" [formGroup]="form">

        <mat-grid-list [cols]="breakpoint" rowHeight="30px" gutterSize="0px" formArrayName="aircraftList" (window:resize)="onResize($event)">
            <mat-grid-tile fxLayout="column"  *ngFor="let aircraftName of aircraftList.value" [formGroup]="aircraftList">
              <mat-checkbox [formControl]="aircraftName.get('selected')">
                <!--{{aircraftName.get('name').value}}-->
                {{aircraftList}}
              </mat-checkbox>

              </mat-grid-tile>
              <mat-grid-tile fxLayout="column" >
                  <mat-checkbox id="toggle-all" ng-model="all" (click)="toggleAll($event)">Toggle All</mat-checkbox>
              </mat-grid-tile>
        </mat-grid-list>
        <div class="close-button">
            <button class="mat-raised-button " routerLink="/home" (click)="close()" style="margin: 10px;position:center">Close</button>
        </div>

      </div>
</div>

在运行时,我从模板中收到一条错误消息,告诉我未定义控件或值(两者都尝试过)。但是当我记录 formArray 时它们就在那里:

我看到的只是一个空白对话框。

我确定我错过了响应式表单的一些简单和基本的东西,但我已经追了 3 天了.....

【问题讨论】:

    标签: angular angular-material


    【解决方案1】:
    <mat-grid-tile fxLayout="column"  *ngFor="let aircraftName of aircraftList.value" [formGroup]="aircraftList">
    

    您还没有定义任何aircraftList 对象。它是一个表单组内的控件:

    this.form = new FormGroup({
      aircraftList: this.aircraftArray
    });
    

    所以你也应该这样访问它:

     <mat-grid-tile fxLayout="column"  *ngFor="let aircraftName of form.controls.aircraftList.value" [formGroup]="aircraftList">
    

    【讨论】:

    • 现在我遇到了一个更奇怪的错误:ERROR TypeError: _v.context.$implicit.get is not a function。仍然没有得到任何复选框。还告诉我 form.controls.aircraftList 没有定义,即使我可以在控制台中看到它
    • 您的代码似乎还有很多其他设计问题。 form.controls.aircraftList.value 可能应该是 form.controls.aircraftList.controls,但这种改变可能需要改变其他的东西。此外,您定义了 aircraftArray 两次。可能只是表面问题。如果你能创建一个 StackBlitz 的例子,它会比静态代码更容易调试,而且你可能会在这个过程中解决一些你自己的问题。
    • 从头开始重新设计了整个组件,又花了一整天的时间研究响应式表单,现在一切正常。当您想进入不那么简单的动态类型表单时,反应式表单并非易事。
    猜你喜欢
    • 1970-01-01
    • 2020-06-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 2021-02-01
    • 2019-12-08
    • 2020-11-20
    相关资源
    最近更新 更多