【问题标题】:Angular Dialog changes are overwriting always the UIAngular Dialog 更改总是覆盖 UI
【发布时间】:2020-09-22 08:21:57
【问题描述】:

我在 Angular 对话框中传递数据,但与此同时,当我在对话框中编辑某些内容时,即使我没有保存它们,它也会覆盖数据。 例如,我有一个对象,然后单击 ot 编辑它。 它会打开一个包含此对象的所有数据的 Angular 对话框。

是否只能在单击保存按钮时更改数据。 我听说 Object.assign 它可能很有用,但不知道如何使用它。 我尝试使用Object.assign,但没有成功。 为什么不起作用我认为 this.data 包含另一个数据作为 this.data.education。 请参阅下面的代码 这是我的对话框代码。

constructor(@Inject(MAT_DIALOG_DATA) public data: EditEducation,
              private dialogRef: MatDialogRef<EducationDialogComponent>,
              public dataService: ModelDataService) { }

  ngOnInit(): void {
    if (!this.data.edit) {
      this.data.education = {} as SubCategory;
    } else {
      ({education: this.data.education} = Object.assign({}, this.data));
    }
  }

这就是我打开对话框的方式。

  <ul>
    <li class="fa fa-pencil addIconTop" (click)="editEducation({edit: true, education: subCategory, model: model})"></li>
    <button (click)="addEducation({edit: false, model: model})" class="btn"><i class="fa fa-plus addIconBottom"></i></button>
    <button [disabled]="education.subCategories.length === 1" (click)="deleteSubCategory(i)" class="btn"><i class="fa fa-trash deleteIconRight"></i></button>
    <li class="fa fa-arrow-down moveIconDown"></li>
    <li class="fa fa-arrow-up moveIconTop"></li>
  </ul>

public editData(data: EditEducation) {
   this.dialog.open(DataDialogComponent, {
        data,
        });
  }
public addData(data: EditEducation) {
    this.dialog.open(DataDialogComponent, {
      data,
    });
  }

这是一个界面,看是否是一个新的对象或需要编辑。

export interface EditEducation {
  education?: SubCategory;
  edit?: boolean;
  model?: Model;
}

这是Education的界面

export interface Education {
  subCategories: EducationSubCategory[];
}


 export interface EducationSubCategory {
  name: string;
  startDate: number;
  endDate: number;
  graduation: string;
  title?: string;
  description: string;
}

【问题讨论】:

  • 是的。在这里创建副本是个好主意。如果您只需要浅拷贝,this.data = Object.assign({}, data);this.data = {...data}; 都是可靠的选择。如果您有嵌套的数组或对象,则需要递归复制。如果需要,请确保打开对话框的代码在保存后可以访问更新的值。
  • 我试过了,但是没有用。我尝试过这样的事情。 ({education: this.data.education} = Object.assign({}, this.data));
  • 它“没用”不是我能帮忙的
  • @AluanHaddad 我编辑了我的评论,它再次覆盖它。是否需要在对话框组件或父组件中进行复制?
  • 你可以在任何一个地方做。如果在对话框中,请在构造函数中执行,在其中注入值。

标签: javascript angular typescript


【解决方案1】:

问题

您正在经历变量通过引用传递的情况

Javascript 有 5 种按值传递的原始数据类型:BooleannullundefinedStringNumber
分配了非原始值的变量将获得对该值的引用。该引用指向对象在内存中的位置。变量实际上并不包含值
当使用 = 将引用类型值(对象)复制到另一个变量时,该值的地址就是实际复制的内容,就好像它是一个原始值一样。 对象是按引用而不是按值复制的

解决方案

解决问题的最简单方法是在分配变量时使用扩展运算符 (...)。下面是应该解决问题的代码重构

constructor(@Inject(MAT_DIALOG_DATA) public data: EditEducation,
              private dialogRef: MatDialogRef<EducationDialogComponent>,
              public dataService: ModelDataService) { }

  ngOnInit(): void {
    if (!this.data.edit) {
      this.data.education = {} as SubCategory;
    } else {
      ({education: this.data.education} = {...this.data };
    }
  }
public editData(data: EditEducation) {
   this.dialog.open(DataDialogComponent, { ...data});
  }
public addData(data: EditEducation) {
    this.dialog.open(DataDialogComponent, {...data});
  }

【讨论】:

  • 在 editData 方法中,我遇到了一个错误。 TS2559: Type '{ education?: EducationSubCategory; edit?: boolean; model?: Model; }' has no properties in common with type 'MatDialogConfig '.
【解决方案2】:

最好在将对象发送到对话框之前复制它。这样您的原始数据就不会被编辑:

   const dialogRef = this.dialog.open(DataDialogComponent, {
     data: _.cloneDeep(data),
   });

对于深度克隆,我建议您使用lodash 库。它有一个名为“cloneDeep”的函数,它复制对象,包括所有嵌套对象。

在您的DataDialogComponent.ts 中,您可以在保存编辑时通过 DialogRef 将更新的数据发送回父组件:

  save(): void {
    this.dialogRef.close(this.data)
  }

在父组件中可以订阅DialogRef并更新原始数据:

   dialogRef.afterClosed().subscribe((updatedData) => {
     if (updatedData) {
       this.data = updatedData;
     }
   });

完整代码

ParentComponent.ts

import { MatDialog } from '@angular/material/dialog';
import { DialogComponent } from '../dialog/dialog.component';
import * as _ from 'lodash';

export class SomeComponent implements OnInit {
  data: Education;

  constructor(public dialog: MatDialog) {}

  public editData(data: EditEducation) {
    const dialogRef = this.dialog.open(DataDialogComponent, {
      data: _.cloneDeep(data),
    });

    dialogRef.afterClosed().subscribe((updatedData) => {
      if (updatedData) {
        this.data = updatedData;
      }
    });
  }
}

DataDialogComponent.ts

import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';

export class DataDialogComponent implements OnInit {

  constructor(
    @Inject(MAT_DIALOG_DATA) public data: EditEducation,
    private dialogRef: MatDialogRef<DataDialogComponent>
  ) {}

  // Implement your methods

  save(): void {
    this.dialogRef.close(this.data)
  }

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

【讨论】:

  • 但是我有一个问题,那就是在父组件中声明的education:Education。该接口将子类别作为子类别。我将添加它的接口。
猜你喜欢
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多