Search code examples
angularangular-materialangular-reactive-forms

Subtasks not displaying in form when clicking "editTask"


I am experiencing an issue where subtasks are not displayed in the form when I click the "editTask" button.

Each task can have multiple subtasks. When I click on a task to edit it, the title of the task populate the form correctly, but the subtasks are not shown.

I expect the subtasks to be displayed as well so that they can be edited if needed.

I am using the Angular Material Chip component to display the subtasks.

Any help or guidance would be greatly appreciated. Thank you!

Here is the relevant code snippet:

STACKBLITZ

main.ts

@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,
      title: 'Task 1',
      subtasks: [
        {
          id: 1,
          taskId: 1,
          description: 'Subtask 1',
        },
        {
          id: 2,
          taskId: 1,
          description: 'Subtask 2',
        },
      ],
    };

    this.dialog
      .open(TaskFormComponent, {
        data: { fromPopup: true, task: task },
      })
      .afterClosed()
      .pipe(filter((task) => task))
      .subscribe((task) => {
        console.log('Edit Task:', task);
      });
  }
}

task-form.component.ts

export class TaskFormComponent {
  protected readonly Object = Object;
  taskForm!: FormGroup;
  fromPopup = false;
  keywords!: string[];
  @ViewChild(ChipFieldComponent) chipFieldComponent!: ChipFieldComponent;
  constructor(
    @Optional()
    @Inject(MAT_DIALOG_DATA)
    public data: { fromPopup: boolean; task: Task }
  ) {}
  ngOnInit() {
    this.keywords = [];
    this.fromPopup = !!this.data?.fromPopup;
    this.taskForm = new FormGroup({
      title: new FormControl(''),
      subTasks: new FormControl(''),
    });
    if (this.data?.task) {
      this.taskForm.setValue({
        title: this.data.task.title,
        subTasks: this.data.task.subtasks.map((x) => x.id),
      });
    }
  }
  public get subTasksFormControl() {
    return this.taskForm.get('subTasks') as FormControl;
  }
  public onSubmit() {
    console.log('Submitted');
  }
}

task-form.component.html

<div mat-dialog-title>Edit Task</div>

<mat-dialog-content>
  <form [formGroup]="taskForm" (ngSubmit)="onSubmit()">
    <mat-form-field>
      <mat-label>Title</mat-label>
      <input
        matInput
        formControlName="title"
        type="text"
        placeholder="Enter a title"
      />
    </mat-form-field>

    <app-chip-field
      [control]="subTasksFormControl"
      [controlTitle]="'subtask'"
    ></app-chip-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>

Solution

  • Yes, you initialized the subtasks to the form control, but not the keywords which is used to display the <mat-chip-row> element.

    Use the ngOnInit() method to initialize the value to the keywords.

    ngOnInit() {
      this.keywords = this.control.value;
    }
    

    Demo @ StackBlitz