简体   繁体   English

在关闭 Angular 材料对话框之前检查用户对反应式表单的更改

[英]Check for user changes of a Reactive form inside an Angular material dialog before closing it

I have a ReactiveForm in a Angular Material Dialog that receives some data to edit it, i want to prevent the user to close if it he has typed something and tried to get out of the dialog.我在 Angular 材质对话框中有一个 ReactiveForm,它接收一些数据来编辑它,我想防止用户在他输入了一些东西并试图退出对话框时关闭它。

If its not modified then close it without asking anything but if it is, i want to show a dialog that says, its modified, are you sure you want to close it?如果它没有被修改,那么在不询问任何内容的情况下关闭它,但如果是,我想显示一个对话框,上面写着,它已修改,你确定要关闭它吗?

I tried to use valueChanges but it shows the confirm dialog as many times as letters have changed.我尝试使用 valueChanges 但它显示确认对话框的次数与字母更改的次数一样多。

This is what i have right now:这就是我现在所拥有的:

ngOnInit() {
  this.preventCloseModal();
  this.source = this.commonFunctions.getSourceFromUrl(this.router.url);
  this.getRequest(this.data);
  this.getNinjas();
  this.getStatus();
}

preventCloseModal() {
  this.addForm.valueChanges.pipe(
    debounceTime(2000),
    distinctUntilChanged()
  ).subscribe(
    (data) => {
      if (this.addForm.dirty) {
        this.dialogRef.disableClose = true;
        this.dialogRef.backdropClick().subscribe(_ => {
          let cn = confirm('Estas seguro que deseas cerrar ? Perderas todos los progresos no guardados.')
          if (cn) {
            this.dialogRef.close();
          }
        })
      }
    });
}

Edit 1:编辑1:

Also i tried the following:我也尝试了以下方法:

async ngOnInit() {
  this.addForm.valueChanges.subscribe((res) => {
    this.isValueChanged = true;
  });
  this.source = this.commonFunctions.getSourceFromUrl(this.router.url);
  this.getRequest(this.data);
  this.getNinjas();
  this.getStatus();
}

@HostListener('window:keyup.esc') onKeyUp() {
  if (this.isValueChanged) {
    // console.log('show alert');
    this.dialogRef.disableClose = true;
    this.dialogRef.backdropClick().subscribe(_ => {
      let cn = confirm('Estas seguro que deseas cerrar ? Perderas todos los progresos no guardados.')
      if (cn) {
        this.dialogRef.close();
      } else {
        return false;
      }
    })
    //return false;
  }
  this.dialogRef.close();
}

I'm blocked, does anyone know how to do it?我被卡住了,有人知道怎么办吗? I tried ngDoCheck but i creates an infinite loop.我尝试了 ngDoCheck 但我创建了一个无限循环。

Thank you!谢谢!

Okay so i found the way that works for me.好的,所以我找到了适合我的方式。

The first thing i did was:我做的第一件事是:
When the form is populated with back-end data, i set it to pristine and untouched.当表单填充有后端数据时,我将其设置为原始且未触及。

this.addForm.markAsUntouched;
this.addForm.markAsPristine;

After that, i check if the user has pressed Esc key or if he has pressed outside the modal.之后,我检查用户是否按下了 Esc 键,或者他是否按下了模态框外。

For the Esc key i did this:对于 Esc 键,我这样做了:

@HostListener('window:keyup.esc') onKeyUp() {
    if (this.addForm.dirty) {
        this.dialogRef.disableClose = true;
        let cn = confirm('Estas seguro que deseas cerrar ? Perderas todos los progresos no guardados.')
        if (cn) {
            this.dialogRef.close();
        } else {
            return false;
        }
    }
    this.dialogRef.close();
}

For the backdrop click i did this one:对于背景点击我做了这个:

constructor(
        ...
) {
        dialogRef.disableClose = true;
        dialogRef.backdropClick().subscribe(() => {
            if (this.addForm.dirty) {
                this.dialogRef.disableClose = true;
                let cn = confirm('Estas seguro que deseas cerrar ? Perderas todos los progresos no guardados.')
                if (cn) {
                    this.dialogRef.close();
                } else {
                    return false;
                }
            }

            this.dialogRef.close();
        })
    }

As you can see, it's the same code but with some different logic, for now, it works, i wanted to share my answer for anyone who is stucked like me.正如您所看到的,它是相同的代码,但具有一些不同的逻辑,现在,它可以工作,我想与像我一样被困住的任何人分享我的答案。 Now it just needs a refactor that i will do so i don't repeat code and it looks cleaner.现在它只需要一个我会做的重构,这样我就不会重复代码并且它看起来更干净。

Thank you very much for your answers @sibabrat swain !非常感谢您的回答@sibabrat swain!

I guess your issues are pretty simple but the execution seems to difficult.我想你的问题很简单,但执行起来似乎很困难。 Let me clear it for you.让我为你清除它。

While you open the dialogue box make sure dialogConfig.disableClose = true;打开对话框时确保dialogConfig.disableClose = true; so that it can only be closed if you trigger to close.这样只有在触发关闭时才能将其关闭。 Follow the code.按照代码。

const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = item;
dialogConfig.width = '76%';
dialogConfig.height = '63%';
dialogConfig.panelClass = 'custome_css_class';
const dialogRef = this.dialog.open(FormBuilderComponent, dialogConfig);

Inside the FormBuilderComponent initialise a variable called as isValueChanged like this.在 FormBuilderComponent 内部初始化一个名为 isValueChanged 的变量,如下所示。

isValueChanged = false;

Now inside the ngOnInit() subscribe the value changes.现在在ngOnInit()中订阅值的变化。 If the value changed make isValueChanged true like this.如果值更改了,则像这样使 isValueChanged 为 true。

async ngOnInit() {
  this.templateForm.valueChanges.subscribe(() => {
      this.isValueChanged = true;
   });
}

No while you click on the button to close the modal check isValueChanged.不,当您单击按钮关闭模式检查 isValueChanged 时。 If that is true then show your alert.如果这是真的,那么请显示您的警报。 And if false then close the modal.如果为假,则关闭模式。

clocseModal() {
   if(this.isValueChanged) {
      // console.log('show alert');
       return false;
   }
 this.dialogRef.close();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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