使用提交按钮时不要使用CanDeactivate保护

时间:2017-03-18 04:47:05

标签: angular

这是我的canDeactivate后卫,它的工作原理。但是当我使用提交按钮时,我不想打电话给警卫。只有当我通过任何其他方式导航时。怎么样?

import { Injectable } from '@angular/core';
import { Router, CanDeactivate } from '@angular/router';
import { FormGroup } from '@angular/forms';

export interface FormComponent {
    myForm: FormGroup;
}

@Injectable()
export class DirtyGuard implements CanDeactivate<FormComponent>  {
  constructor(private router: Router) {}

  canDeactivate(component: FormComponent) {
      console.log(component.myForm)
        if (component.myForm.dirty ){
            return confirm('You have unsaved changes. Are you sure you want to navigate away?');
        }
        return true;
  }
}

 <button md-raised-button [disabled]="!myForm.valid" type="submit" color="primary">
                            <i class="material-icons">arrow_forward</i>
                            Exposures: Currencies
                        </button>

4 个答案:

答案 0 :(得分:3)

[棱角v.4 - 在v.2上未经测试,但应该有效]

警卫可以停用&#39;正确调用,但您只想在您提交的方案中返回true,那么我们如何确定?您已经拥有FormGroup的句柄,但是这似乎没有与提交相关的属性。作为替代方法,您可以使用组件类中的@ViewChild装饰器获取表单句柄,如下所示:

<form #myForm="ngForm" (ngSubmit)="onSubmit()">

为了使其正常工作,您必须为表单添加一个局部变量,如下所示:

if (this.myForm.form.dirty && !this.myForm._submitted ){
    return confirm('You have unsaved changes. Are you sure you want to navigate away?');
}
return true;

然后,您将在myForm对象上看到一个名为_submitted的属性。这允许您更新if条件,以便仅在脏&amp;&amp ;;时显示确认消息。 !提交。 e.g:

https://channel9.msdn.com/Events/Visual-Studio/Visual-Studio-2017-Launch/WEB-103

我假设您已经根据发布的日期解决了这个问题,但这可能有助于解释至少发生了什么。

答案 1 :(得分:0)

在我们的组件中,可以使用canDeactivate方法根据需要欺骗警报。

组件:

import { ComponentCanDeactivate } from './pending-changes.guard';
import { HostListener } from '@angular/core';
import { Observable } from 'rxjs/Observable';

export class MyComponent implements ComponentCanDeactivate {
 @ViewChild('RegisterForm')
 form: NgForm;

  // @HostListener allows us to also guard against browser refresh, close, etc.
  @HostListener('window:beforeunload')
  canDeactivate(): Observable<boolean> | boolean {
    // insert logic to check if there are pending changes here;
    // returning true will navigate without confirmation
    // returning false will show a confirm dialog before navigating away
    return this.form.submitted || !this.form.dirty; // insert your code here for submit event 

  }
}

警卫:

import { CanDeactivate } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

export interface ComponentCanDeactivate {
  canDeactivate: () => boolean | Observable<boolean>;
}

@Injectable()
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
  canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
    // if there are no pending changes, just allow deactivation; else confirm first
    return component.canDeactivate() ?
      true :
      // NOTE: this warning message will only be shown when navigating elsewhere within your angular app;
      // when navigating away from your angular app, the browser will show a generic warning message
      // see https://stackoverflow.com/questions/52044306/how-to-add-candeactivate-functionality-in-component
      confirm('WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.');
  }
}

路线:

import { PendingChangesGuard } from './pending-changes.guard';
import { MyComponent } from './my.component';
import { Routes } from '@angular/router';

export const MY_ROUTES: Routes = [
  { path: '', component: MyComponent, canDeactivate: [PendingChangesGuard] },
];

模块:

import { PendingChangesGuard } from './pending-changes.guard';
import { NgModule } from '@angular/core';

@NgModule({
  // ...
  providers: [PendingChangesGuard],
  // ...
})
export class AppModule {}

答案 2 :(得分:0)

我假设您在用户点击“提交”按钮后便离开了。表单有效时,禁用can deactivate防护的问题是,在表单完全填写完毕而失去所有工作后,用户可能会意外按下“取消/返回”按钮等。换句话说,仅因为表单有效,并不表示您想停用can-deactivate防护。

如果要导航,可以在路线导航之前在onSubmit函数中将属性设置为“ true”,并在保护逻辑中使用它。

组件  (反应形式)

export class MyComponent {

// ..

submitSuccess: boolean;

canDeactivate(): boolean | Observable<boolean> | Promise<boolean> {
   if (!this.inputForm.dirty || this.submitSuccess ) {
    return true;
  }
return this.confirmDialogService.confirm('Discard changes?');
}

// ...
  onSubmit() {
    this.submitSuccess = true; 
    this.router.navigate(['my-page']);
  }
}

确认对话框服务

import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';

@Injectable({
providedIn: 'root'
})
export class ConfirmationDialogService {
/**
* Ask user to confirm an action. `message` explains the action and choices.
* Returns observable resolving to `true`=confirm or `false`=cancel
*/
 confirm(message?: string): Observable<boolean> {
 const confirmation = window.confirm(message || 'Are you sure? Your changes 
 will be lost.');

return of(confirmation);
 }
}

可以停用防护功能

export interface CanComponentDeactivate {
canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}
@Injectable({
  providedIn: 'root',
})
export class CanDeactivateGuard implements 
CanDeactivate<CanComponentDeactivate> {
  canDeactivate(component: CanComponentDeactivate) {
    return component.canDeactivate ? component.canDeactivate() : true;
   }
}

路线

\\ ...
children: [
  { path: 'my-path', component: MyComponent, canDeactivate: 
[CanDeactivateGuard] },

]},

// ..

希望有帮助!

答案 3 :(得分:0)

回答晚了,但可能会有所帮助。如果表单已提交并且我们希望将用户导航到另一条路线,则在导航之前重置表单。

前 -

this.service.addUser(this.userForm).subscribe((res) => {
    this.addUser.reset();
    this.router.navigate(['/link to another page']);
});