Javascript 角度对话框更改总是覆盖UI
我在一个角度对话框中传递数据,但与此同时,当我在对话框中编辑某些内容时,它会覆盖数据,即使我没有保存它们。 例如,我有一个对象并单击“编辑”。 它将打开一个包含此对象所有数据的角度对话框 是否只能在单击“保存”按钮时更改数据。 我听说了Object.assign,它可能很有用,但不知道如何使用它。 我尝试了Javascript 角度对话框更改总是覆盖UI,javascript,angular,typescript,Javascript,Angular,Typescript,我在一个角度对话框中传递数据,但与此同时,当我在对话框中编辑某些内容时,它会覆盖数据,即使我没有保存它们。 例如,我有一个对象并单击“编辑”。 它将打开一个包含此对象所有数据的角度对话框 是否只能在单击“保存”按钮时更改数据。 我听说了Object.assign,它可能很有用,但不知道如何使用它。 我尝试了对象。分配,但无效。 为什么不起作用?我认为this.data包含另一个数据,即this.data.education。 请参见下面的代码 这是我的对话框代码 constructor(@Inj
对象。分配
,但无效。
为什么不起作用?我认为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 Education {
subCategories: EducationSubCategory[];
}
export interface EducationSubCategory {
name: string;
startDate: number;
endDate: number;
graduation: string;
title?: string;
description: string;
}
最好在将对象发送到对话框之前复制该对象。这样您的原始数据就不会被编辑:
const dialogRef = this.dialog.open(DataDialogComponent, {
data: _.cloneDeep(data),
});
对于深度克隆,我建议您使用库。它有一个名为“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;
}
});
}
}
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()
}
}
DataDialogComponent.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;
}
});
}
}
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()
}
}
从'@angular/material/DIALOG'导入{MatDialogRef,MAT_DIALOG_DATA};
导出类DataDialogComponent实现OnInit{
建造师(
@注入(MAT_DIALOG_DATA)公共数据:EditEducation,
私有dialogRef:MatDialogRef
) {}
//实施你的方法
save():void{
this.dialogRef.close(this.data)
}
放弃():无效{
this.dialogRef.close()
}
}
问题
您正在体验通过引用传递变量的情况
Javascript有5种按值传递的基本数据类型:Boolean
、null
、undefined
、String
和Number
分配了非原语值的变量将引用该值。该引用指向对象在内存中的位置。变量实际上不包含值
当引用类型值(对象)使用=,复制到另一个变量时,该值的地址就是实际复制的地址,就像它是一个原语一样对象是通过引用而不是通过值复制的 解决方案 解决此问题的最简单方法是在分配变量时使用扩展运算符
(…)
。下面是代码的重构,应该可以解决这个问题
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 };
}
}
是 啊在这里创建副本是个好主意
this.data=Object.assign({},data)
或this.data={…data}如果您只需要一个浅拷贝,代码>都是可靠的替代方案。如果有嵌套数组或对象,则需要递归复制。如果需要,请确保打开对话框的代码在保存后可以访问更新的值。我已经尝试过,但没有成功。我试过这样的东西<代码>({education:this.data.education}=Object.assign({},this.data))代码>它“不起作用”不是我能帮助的with@AluanHaddad我编辑了我的评论,它再次覆盖了它。我需要在对话框组件或父组件中进行复制吗?您可以在任一位置进行复制。如果在对话框中,则在构造函数中执行,在构造函数中注入值。但我有一个问题,那就是父组件中声明的education:education
。该接口将子类作为子类别。我将添加它的接口。在editData方法中,我面临一个错误,它是这样说的<代码>TS2559:类型“{education?:EducationSubCategory;edit?:boolean;model?:model;}”与类型“MatDialogConfig”没有共同的属性。