在我的函数 ngDoCheck() 中关闭我的 matDialog 时出现问题 Angular
Problem closing my matDialog in my function ngDoCheck() Angular
我在 ngDoCheck()
函数中关闭 Angular Material 的 matDialog
时遇到问题。
编辑: StackBlitz HERE
解释:
在我的主页上,我有一个按钮可以打开 matDialog
以将数据提取或不提取到 Excel 文件中。
在我的 matDialog
中,我有两个按钮。
一个关闭 matDialog
,另一个启动函数 extractWallet()
,
恢复数据库中的数据。
在这个函数中,我使用 waitExtraction
变量禁用我的按钮,并禁用 matDialog
的关闭,直到提取完成。
我的 loadInvoiceExtractionXXX()
方法允许我恢复我的数据库数据,一旦收到数据,
completedExtraction
设置为 [false, false, false]
在函数对应的索引(0、1 或 2)上设置为 true
。
在我的 ngOnInit()
中,数据通过 Observer
接收并保存在局部变量中。
因此在extractWallet()
.
中执行loadInvoiceExtractionXXX()
后接收到新数据
我的问题发生在这里。我有一个 ngDoCheck()
函数,用于检查何时使用 this.completedExtraction=[true, true, true]
接收到所有三个数据。
我的 Excel 文件已创建并上传到浏览器。
提取现已完成,我现在想用 this.dialogRef.close()
.
关闭我的 matDialog
但是显示如下错误:
Error: ExpressionChangedAfterItHasBeenCheckedError:
Expression has changed after it was checked.
Previous value: '@dialogContainer: enter'.
Current value: '@dialogContainer: exit'.
我试图在 ngAfterViewChecked()
中关闭我的 matDialog
,但显示相同的错误。
如果有人有解决方案让我在提取后关闭我的 matDialog
,我会很感兴趣。
我把我的代码交给你了:
export class ExtractWalletComponent implements OnInit, DoCheck, OnDestroy {
private subscription$: Subscription = new Subscription();
selectedWallet: Wallet;
waitExtraction: boolean;
completedExtraction: boolean[];
invoiceProduct: InvoiceExtractionProduct[];
invoiceSupport: InvoiceExtractionSupport[];
invoiceTraining: InvoiceExtractionTraining[];
constructor(public dialogRef: MatDialogRef<ExtractWalletComponent>,
public storeWallets: WalletsComponentStore,
public snackBar: MatSnackBar) { }
ngOnInit(): void {
this.waitExtraction = false;
this.completedExtraction = [false, false, false];
this.subscription$.add(this.storeWallets.selectedWallet$.subscribe(wallet => this.selectedWallet = wallet));
this.subscription$.add(this.storeWallets.invoiceExtractionProduct$.subscribe(invoiceProduct => this.invoiceProduct = invoiceProduct));
this.subscription$.add(this.storeWallets.invoiceExtractionSupport$.subscribe(invoiceSupport => this.invoiceSupport = invoiceSupport));
this.subscription$.add(this.storeWallets.invoiceExtractionTraining$.subscribe(invoiceTraining => this.invoiceTraining = invoiceTraining));
}
ngDoCheck(): void {
if(this.completedExtraction[0] == true && this.completedExtraction[1] == true && this.completedExtraction[2] == true) {
this.completedExtraction[0] = false;
this.completedExtraction[1] = false;
this.completedExtraction[2] = false;
this.dialogRef.disableClose = false;
const wb: XLSX.WorkBook = XLSX.utils.book_new();
const ws1: XLSX.WorkSheet = XLSX.utils.json_to_sheet(this.invoiceProduct);
const ws2: XLSX.WorkSheet = XLSX.utils.json_to_sheet(this.invoiceSupport);
const ws3: XLSX.WorkSheet = XLSX.utils.json_to_sheet(this.invoiceTraining);
XLSX.writeFile(wb, this.selectedWallet.user.num_seller + '_' + this.selectedWallet.period.month +
'_' + this.selectedWallet.period.year + '_' + this.selectedWallet.id + '.xlsx');
this.dialogRef.close(); //<-- ERROR
}
}
ngOnDestroy(): void {
this.subscription$.unsubscribe();
this.storeWallets.clearExtraction();
}
extractWallet(): void {
this.waitExtraction = true;
this.dialogRef.disableClose = true;
this.snackBar.open('Extraction en cours', 'OK', { duration: 5000 });
this.storeWallets.loadInvoiceExtractionProduct(this.selectedWallet).subscribe(
res => {
if(res) { this.completedExtraction[0] = true;}
},
err => { console.error(err); this.dialogRef.close(); this.snackBar.open('Echec de l\'extraction', 'OK', { duration: 2000 }); }
);
this.storeWallets.loadInvoiceExtractionSupport(this.selectedWallet).subscribe(
res => {
if(res) { this.completedExtraction[1] = true; }
},
err => { console.error(err); this.dialogRef.close(); this.snackBar.open('Echec de l\'extraction', 'OK', { duration: 2000 }); }
);
this.storeWallets.loadInvoiceExtractionTraining(this.selectedWallet).subscribe(
res => {
if(res) { this.completedExtraction[2] = true; }
},
err => { console.error(err); this.dialogRef.close(); this.snackBar.open('Echec de l\'extraction', 'OK', { duration: 2000 }); }
);
}
}
预先感谢您的帮助。
PS: 对不起我的英文(Google 翻译)。
好吧,问题正是它告诉您的内容:您正在更改检测周期中更改某些内容。您需要将更改放在循环之外,例如:
ngDoCheck(): void {
if(this.completedExtraction[0] == true && this.completedExtraction[1] == true && this.completedExtraction[2] == true) {
// omitted
// Run after change detection
setTimeout(() => this.dialogRef.close());
}
}
但我认为主要问题是您正在滥用 ngDoCheck
生命周期挂钩。你为什么不直接对 Observables 做出反应?
combineLatest([
this.storeWallets.loadInvoiceExtractionProduct(this.selectedWallet)
.pipe(/* Add your catchError logic for only this observable */),
this.storeWallets.loadInvoiceExtractionSupport(this.selectedWallet),
this.storeWallets.loadInvoiceExtractionTraining(this.selectedWallet),
]).pipe(
filter(results => results.every(res => !!res))
).subscribe(results => {
// Called when all 3 returned positively
})
我在 ngDoCheck()
函数中关闭 Angular Material 的 matDialog
时遇到问题。
编辑: StackBlitz HERE
解释:
在我的主页上,我有一个按钮可以打开 matDialog
以将数据提取或不提取到 Excel 文件中。
在我的 matDialog
中,我有两个按钮。
一个关闭 matDialog
,另一个启动函数 extractWallet()
,
恢复数据库中的数据。
在这个函数中,我使用 waitExtraction
变量禁用我的按钮,并禁用 matDialog
的关闭,直到提取完成。
我的 loadInvoiceExtractionXXX()
方法允许我恢复我的数据库数据,一旦收到数据,
completedExtraction
设置为 [false, false, false]
在函数对应的索引(0、1 或 2)上设置为 true
。
在我的 ngOnInit()
中,数据通过 Observer
接收并保存在局部变量中。
因此在extractWallet()
.
loadInvoiceExtractionXXX()
后接收到新数据
我的问题发生在这里。我有一个 ngDoCheck()
函数,用于检查何时使用 this.completedExtraction=[true, true, true]
接收到所有三个数据。
我的 Excel 文件已创建并上传到浏览器。
提取现已完成,我现在想用 this.dialogRef.close()
.
matDialog
但是显示如下错误:
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
Previous value: '@dialogContainer: enter'. Current value: '@dialogContainer: exit'.
我试图在 ngAfterViewChecked()
中关闭我的 matDialog
,但显示相同的错误。
如果有人有解决方案让我在提取后关闭我的 matDialog
,我会很感兴趣。
我把我的代码交给你了:
export class ExtractWalletComponent implements OnInit, DoCheck, OnDestroy {
private subscription$: Subscription = new Subscription();
selectedWallet: Wallet;
waitExtraction: boolean;
completedExtraction: boolean[];
invoiceProduct: InvoiceExtractionProduct[];
invoiceSupport: InvoiceExtractionSupport[];
invoiceTraining: InvoiceExtractionTraining[];
constructor(public dialogRef: MatDialogRef<ExtractWalletComponent>,
public storeWallets: WalletsComponentStore,
public snackBar: MatSnackBar) { }
ngOnInit(): void {
this.waitExtraction = false;
this.completedExtraction = [false, false, false];
this.subscription$.add(this.storeWallets.selectedWallet$.subscribe(wallet => this.selectedWallet = wallet));
this.subscription$.add(this.storeWallets.invoiceExtractionProduct$.subscribe(invoiceProduct => this.invoiceProduct = invoiceProduct));
this.subscription$.add(this.storeWallets.invoiceExtractionSupport$.subscribe(invoiceSupport => this.invoiceSupport = invoiceSupport));
this.subscription$.add(this.storeWallets.invoiceExtractionTraining$.subscribe(invoiceTraining => this.invoiceTraining = invoiceTraining));
}
ngDoCheck(): void {
if(this.completedExtraction[0] == true && this.completedExtraction[1] == true && this.completedExtraction[2] == true) {
this.completedExtraction[0] = false;
this.completedExtraction[1] = false;
this.completedExtraction[2] = false;
this.dialogRef.disableClose = false;
const wb: XLSX.WorkBook = XLSX.utils.book_new();
const ws1: XLSX.WorkSheet = XLSX.utils.json_to_sheet(this.invoiceProduct);
const ws2: XLSX.WorkSheet = XLSX.utils.json_to_sheet(this.invoiceSupport);
const ws3: XLSX.WorkSheet = XLSX.utils.json_to_sheet(this.invoiceTraining);
XLSX.writeFile(wb, this.selectedWallet.user.num_seller + '_' + this.selectedWallet.period.month +
'_' + this.selectedWallet.period.year + '_' + this.selectedWallet.id + '.xlsx');
this.dialogRef.close(); //<-- ERROR
}
}
ngOnDestroy(): void {
this.subscription$.unsubscribe();
this.storeWallets.clearExtraction();
}
extractWallet(): void {
this.waitExtraction = true;
this.dialogRef.disableClose = true;
this.snackBar.open('Extraction en cours', 'OK', { duration: 5000 });
this.storeWallets.loadInvoiceExtractionProduct(this.selectedWallet).subscribe(
res => {
if(res) { this.completedExtraction[0] = true;}
},
err => { console.error(err); this.dialogRef.close(); this.snackBar.open('Echec de l\'extraction', 'OK', { duration: 2000 }); }
);
this.storeWallets.loadInvoiceExtractionSupport(this.selectedWallet).subscribe(
res => {
if(res) { this.completedExtraction[1] = true; }
},
err => { console.error(err); this.dialogRef.close(); this.snackBar.open('Echec de l\'extraction', 'OK', { duration: 2000 }); }
);
this.storeWallets.loadInvoiceExtractionTraining(this.selectedWallet).subscribe(
res => {
if(res) { this.completedExtraction[2] = true; }
},
err => { console.error(err); this.dialogRef.close(); this.snackBar.open('Echec de l\'extraction', 'OK', { duration: 2000 }); }
);
}
}
预先感谢您的帮助。
PS: 对不起我的英文(Google 翻译)。
好吧,问题正是它告诉您的内容:您正在更改检测周期中更改某些内容。您需要将更改放在循环之外,例如:
ngDoCheck(): void {
if(this.completedExtraction[0] == true && this.completedExtraction[1] == true && this.completedExtraction[2] == true) {
// omitted
// Run after change detection
setTimeout(() => this.dialogRef.close());
}
}
但我认为主要问题是您正在滥用 ngDoCheck
生命周期挂钩。你为什么不直接对 Observables 做出反应?
combineLatest([
this.storeWallets.loadInvoiceExtractionProduct(this.selectedWallet)
.pipe(/* Add your catchError logic for only this observable */),
this.storeWallets.loadInvoiceExtractionSupport(this.selectedWallet),
this.storeWallets.loadInvoiceExtractionTraining(this.selectedWallet),
]).pipe(
filter(results => results.every(res => !!res))
).subscribe(results => {
// Called when all 3 returned positively
})