При нажатии на «Редактировать задачу» открывается форма, которая уже содержит значения задачи. Это уже работает для простых строк, но не для значений, имеющих массив значений.
Проблема:
Задачу можно поручить нескольким людям. Однако люди, которые уже назначены, не выбираются.
Я уже исследовал, но не смог реализовать решение в своем коде:
patchValue для объекта FormArray?
Как использовать FormArray в angular
Демо-версия Stackblitz:
https://stackblitz.com/edit/stackblitz-starters-1ksmca?file=src%2Fmain.ts
Самый актуальный код:
ts-файл:
export class TaskFormComponent {
protected readonly Object = Object;
taskForm!: FormGroup;
fromPopup = false;
constructor(
@Optional()
@Inject(MAT_DIALOG_DATA)
public data: { fromPopup: boolean; task: Task }
) {}
ngOnInit() {
this.fromPopup = !!this.data?.fromPopup;
this.taskForm = new FormGroup({
assignedTo: new FormControl(''),
});
if (this.data?.task) {
this.taskForm.setValue({
assignedTo: this.data.task.contacts,
});
}
}
public onSubmit() {
console.info('Submitted');
}
}
html-файл:
<div>
<div>
<div mat-dialog-title>Edit Task</div>
</div>
<mat-dialog-content>
<form [formGroup] = "taskForm" (ngSubmit) = "onSubmit()">
<mat-form-field>
<mat-label>Assigned to</mat-label>
<mat-icon color = "primary" matSuffix>group_add</mat-icon>
<mat-select formControlName = "assignedTo" multiple>
@for (contact of this.data.task.contacts; track contact.id) {
<mat-option [value] = "contact.id">{{ contact.name }}</mat-option>
}
</mat-select>
</mat-form-field>
</form>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button color = "primary" type = "submit">
{{ data?.task ? 'Update Task' : 'Create Task' }}
</button>
<button mat-raised-button mat-dialog-close type = "button" color = "warn">
Close
</button>
</mat-dialog-actions>
</div>





Вопрос может показаться слишком широким, но я постараюсь ответить, сосредоточив внимание на первоначальном вопросе. Один из способов получить доступ к значению массива в HTML — перебрать переменную с помощью NgFor, например:
<ul>
<li *ngFor = "let item of items">{{ item }}</li>
</ul>
Если это ответ на вопрос ОП (и я не говорю, что это не так), то этот вопрос должен быть дубликатом; не может быть, чтобы этот вопрос еще не был задан и на него не был дан ответ на этом сайте.
Поскольку ОП спрашивает о формах, возможно, пример API FormArray будет лучшим предложением?
Поскольку вы установили значение параметров выбора в поле id.
...
<mat-option [value] = "contact.id">{{ contact.name }}</mat-option>
...
Мы также должны использовать patchValue для идентификаторов как массива, для этого мы используем оператор карты javascript, чтобы получить только идентификаторы из массива объектов!
...
if (this.data?.task) {
this.taskForm.setValue({
assignedTo: this.data.task.contacts.map((x) => x.id),
});
}
...
ТС
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Inject, Optional } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckbox } from '@angular/material/checkbox';
import {
MatError,
MatFormField,
MatFormFieldModule,
MatLabel,
} from '@angular/material/form-field';
import {
FormControl,
FormGroup,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatInputModule } from '@angular/material/input';
import { MatOption, provideNativeDateAdapter } from '@angular/material/core';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { TitleCasePipe } from '@angular/common';
import { MatSelect } from '@angular/material/select';
import { MatIconModule } from '@angular/material/icon';
import { MatRadioButton, MatRadioGroup } from '@angular/material/radio';
import {
MAT_DIALOG_DATA,
MatDialog,
MatDialogModule,
MatDialogRef,
} from '@angular/material/dialog';
import { Task } from '../../app/task';
@Component({
selector: 'app-task-form',
standalone: true,
imports: [
CommonModule,
MatButtonModule,
MatCheckbox,
MatError,
MatFormField,
MatLabel,
ReactiveFormsModule,
MatDatepickerModule,
MatInputModule,
MatFormFieldModule,
MatButtonToggleModule,
TitleCasePipe,
MatSelect,
MatOption,
MatRadioGroup,
MatRadioButton,
MatDialogModule,
MatIconModule,
],
templateUrl: './task-form.component.html',
styleUrl: './task-form.component.css',
})
export class TaskFormComponent {
protected readonly Object = Object;
taskForm!: FormGroup;
fromPopup = false;
constructor(
@Optional()
@Inject(MAT_DIALOG_DATA)
public data: { fromPopup: boolean; task: Task }
) {}
ngOnInit() {
this.fromPopup = !!this.data?.fromPopup;
this.taskForm = new FormGroup({
assignedTo: new FormControl(''),
});
if (this.data?.task) {
this.taskForm.setValue({
assignedTo: this.data.task.contacts.map((x) => x.id),
});
}
}
public onSubmit() {
console.info('Submitted');
}
}
<div>
<div>
<div mat-dialog-title>Edit Task</div>
</div>
<mat-dialog-content>
<form [formGroup] = "taskForm" (ngSubmit) = "onSubmit()">
<mat-form-field>
<mat-label>Assigned to</mat-label>
<mat-icon color = "primary" matSuffix>group_add</mat-icon>
<mat-select formControlName = "assignedTo" multiple>
@for (contact of this.data.task.contacts; track contact.id) {
<mat-option [value] = "contact.id">{{ contact.name }}</mat-option>
}
</mat-select>
</mat-form-field>
</form>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-raised-button color = "primary" type = "submit">
{{ data?.task ? 'Update Task' : 'Create Task' }}
</button>
<button mat-raised-button mat-dialog-close type = "button" color = "warn">
Close
</button>
</mat-dialog-actions>
</div>
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { TaskFormComponent } from './app/task-form/task-form.component';
import { filter } from 'rxjs';
import 'zone.js';
import { MatDialog } from '@angular/material/dialog';
import { Task } from './app/task';
import { provideAnimations } from '@angular/platform-browser/animations';
@Component({
selector: 'app-root',
standalone: true,
imports: [TaskFormComponent],
template: `
<button (click) = "editTask()">Edit Task</button>
`,
})
export class App {
name = 'Angular';
constructor(private dialog: MatDialog) {}
public editTask() {
let task: Task = {
id: 1,
contacts: [
{
id: 1,
name: 'John Doe',
},
{
id: 2,
name: 'Jane Doe',
},
],
};
this.dialog
.open(TaskFormComponent, {
data: { fromPopup: true, task: task },
})
.afterClosed()
.pipe(filter((task) => task))
.subscribe((task) => {
console.info('Edit Task');
});
}
}
bootstrapApplication(App, {
providers: [provideAnimations()],
}).catch((err) => console.error(err));
Я думал, что вы могли бы сделать это с помощью FormArray. Был бы такой подход правильным?
@coder массив формы, мы можем передать входной массив, но нам нужно убедиться, что значение раскрывающегося списка выбора правильное, здесь мы используем contact.id в качестве ключа, поэтому нам нужно передать массив чисел, если мы просто используем [value] = "contact" тогда нам не нужно будет преобразовывать массив в массив чисел!
Сейчас ваш вопрос слишком широк. Это звучит как «реализуйте этот код для меня», что не по теме этого сайта. Если это не ваше намерение и у вас есть конкретный вопрос о целевой части вашего решения, вам следует отредактировать свой вопрос, чтобы было ясно, что это такое.