#angular #angular-material
#angular #угловой-материал
Вопрос:
Я хочу, чтобы мат-флажки были заполнены из массива. Я могу создать группу форм и массив форм и просмотреть их содержимое в консоли. Но я не могу получить список устройств для отображения с помощью 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 дня…..
Ответ №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">
Комментарии:
1. Теперь я получаю еще более странную ошибку: ОШИБКА TypeError: _v.context.$implicit.get не является функцией. По-прежнему не получает никаких флажков. Также сообщает мне, что form.controls.aircraftList не определен, хотя я вижу его в консоли
2. Похоже, что в вашем коде много других проблем с дизайном.
form.controls.aircraftList.value
вероятно, должно бытьform.controls.aircraftList.controls
, но это изменение может потребовать изменения других вещей. Кроме того, вы определяетеaircraftArray
дважды. Возможно, это только поверхностный. Если вы сможете создать пример StackBlitz, его будет намного проще отлаживать, чем статический код, плюс вы, вероятно, разберетесь с некоторыми своими проблемами в процессе.3. Переработал весь компонент с нуля, потратил еще один полный день на изучение реактивных форм, и теперь все работает так, как должно. Реактивные формы не являются тривиальными, когда вы хотите перейти к не таким простым формам динамического типа.