Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

201
Visualizações
do not use CanDeactivate guard when using submit button

Here is my canDeactivate guard and it works. But I dont want to call the guard when I use the submit button. Only when I navigate by any other means. How?

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>
about 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

[angular v.4 - untested on v.2, but should work]

The guard 'canDeactivate' is correctly getting called, but you just want to return true for the scenario where you've submitted, so how can we determine that? You already have a handle to the FormGroup, however this does not appear to have a property relating to submitted. As an alternative, you can obtain a handle to your form using the @ViewChild decorator within your component class, like so:

@ViewChild('myForm') myForm;

In order for this to work you'll have to add a local variable for your form, like so:

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

you will then see a property on the myForm object called _submitted. This allows you to update your if condition to only show the confirm message if dirty && !submitted. e.g.:

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

I'm assuming you've already worked round this issue, based on the date posted, but this might serve to explain what was going on at least.

about 4 years ago · Santiago Trujillo Relatório

0

In our component we can trick alert according to our need by using canDeactivate method.

Component:

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 

  }
}

Guard:

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.');
  }
}

Routes:

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] },
];

Module:

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

@NgModule({
  // ...
  providers: [PendingChangesGuard],
  // ...
})
export class AppModule {}
about 4 years ago · Santiago Trujillo Relatório

0

I assume that you are navigating away after the user hits the submit button. The problem with disabling the can deactivate guard when the form is valid, is that the user could accidentally hit cancel/back button, etc., after the form is completely filled out losing all of their work. In other words, just because the form is valid does not mean you would want to deactivate the can-deactivate guard.

If you are navigating away, you can set a property to "true" in the onSubmit function before the route navigation and use it in your guard logic.

Component (reactive forms)

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']);
  }
}

Confirm Dialog Service

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);
 }
}

Can Deactivate Guard

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;
   }
}

Routes

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

]},

// ..

Hope it helps!

about 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda