简体   繁体   中英

Angular 14 - How to break two way binding on formgroups inside formarray for mat-dialog?

My problem is detailed lower down. I have a mat-dialog that is used to edit a previous data entry. Each entry has a FormGroup in the form of a Deliverable. So a FormControl name, and a FormArray Steps. Then the FormArray Steps has a FormGroup with two FormControls. Something like this:

// TOTALLY PSEUDO
Deliverable = FormGroup({
  name: FormControl,
  steps: FormArray[FormGroup({
    step_num: FormControl,
    step_name: FormControl
  }), FormGroup({
    step_num: FormControl,
    step_name: FormControl
  })]
})

Edit function:


export interface Deliverable {
  name: string,
  steps: any[]
}

edit(deliverable: Deliverable) {
  const tempSteps = Object.assign([], deliverable.steps)
  const dialogRef = this.dialog.open(DeliverableDialogComponent, {
    data: { name: deliverable.name, steps: tempSteps }
  })

  dialogRef.afterClosed().subscribe(result => {
    console.log(result)
  })
}

On the DeliverableDialogComponent.html:

<mat-dialog-content>
    <mat-form-field class="form-field" appearance="outline">
        <mat-label>Deliverable Name</mat-label>
        <input matInput type="text" autocomplete="off" [(ngModel)]="data.name" />
    </mat-form-field>
    <div *ngFor="let step of data.steps; let stepIndex=index">
        <mat-form-field class="form-field" appearance="outline">
            <mat-label>Step Number</mat-label>
            <input matInput type="text" autocomplete="off" [(ngModel)]="step.step_num">
        </mat-form-field>
        <mat-form-field class="form-field" appearance="outline">
            <mat-label>Step Name</mat-label>
            <input matInput type="text" autocomplete="off" [(ngModel)]="step.step_name">
        </mat-form-field>
    </div>
</mat-dialog-content>

On the DeliverableDialogComponent.ts:

import { Component, Inject, OnInit } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';

export interface Deliverable {
  name: string;
  steps: any[];
}

@Component({
  selector: 'app-deliverable-dialog',
  templateUrl: './deliverable-dialog.component.html',
  styleUrls: ['./deliverable-dialog.component.scss']
})
export class DeliverableDialogComponent implements OnInit {

  constructor(public dialogRef: MatDialogRef<DeliverableDialogComponent>,
              @Inject(MAT_DIALOG_DATA) public data: Deliverable) { }

  onNoClick(): void {
    this.dialogRef.close()
  }

  ngOnInit(): void {
  }
}

My problem is that there is a two way connection for the steps, both step_num and step_name. So when I make a change in the dialog, it is updating the step_num and step_name on the original component. I don't want this functionality as I only want it to update when I click save, and to not update when I hit cancel or just click out of the dialog. The Deliverable.name works fine, but the steps are two way binded.

I solved this problem by making a deepcopy of deliverable.steps by using this:

const tempSteps = JSON.stringify(JSON.parse(deliverable.steps))

//INSTEAD OF

const tempSteps = Object.assign([], deliverable.steps)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM