Angular Two buttons to submit a form but with different purpose
Asked Answered
S

10

27

I have an angular reactive form

<form [formGroup]="form" (ngSubmit)="onSubmit()">

I have two buttons to submit. I need to perform a common operation when users press the button, that is submit the form, but also I need to differentiate between the buttons, because I need to redirect the user to different pages, depending on the button pressed. Here is my two buttons:

<button name="Previous" type="submit" [disabled]="form.invalid"> Previous</button>
<button name="Next" type="submit" [disabled]="form.invalid">Next</button>

How can I know in the OnSubmit event which button was pressed?

Sosthina answered 29/6, 2018 at 9:24 Comment(1)
if you are using wizard it's better to not check validity in Previous step!Hagan
S
6

I found an answer. A bit tricky: In the onSubmit event I check:

var buttonName = document.activeElement.getAttribute("Name");

Since one of the button must be the active element on the form when the user click it, this does the trick for me

Sosthina answered 29/6, 2018 at 9:37 Comment(1)
how to do it in angular?Dessiatine
A
25

user1238784, you shouldn't use document directly in Angular, use ElementRef or Renderer2 instead. While this works, it's against best practices and it will break SSR if you decide to use Angular Universal at some point.

Direct DOM manipulation in Angular is big no no, you should always manipulate DOM using API provided by framework.

But you don't even need any of that, you can pass event as param like this:

<form [formGroup]="form" (ngSubmit)="onSubmit($event.submitter.id)">

and then in component you can use event to identify button that was clicked

this is how you can access the id of the input/button being used to submit the form

submitForm(event : MouseEvent) :void
  {
    console.log(event)
  }
Adventitia answered 25/4, 2019 at 7:25 Comment(5)
This was really helpful, thank you. I was able to use $event.submitter.id within the onSubmit function to distinguish the buttons.Bechance
this is such an excellent solution Thank you for sharing.Calvano
$event.submitter.id is not supported in SafariAideaidedecamp
@Aideaidedecamp it is now supported in Safari see: developer.mozilla.org/en-US/docs/Web/API/SubmitEvent/submitterPleomorphism
does it provide cross browser support?Dessiatine
R
20

Try this.

In your component.ts

import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  form: FormGroup;
  nextClicked = false;


  constructor(private fb: FormBuilder) {
   this.form = this.fb.group({
     age: [20],
     name: ['asdas']
   });
  }

  public onSubmit(): void {
    if(this.nextClicked) {
     ////
    }else {
      ////
    }

  }

  public onNextClick(): void {
    this.nextClicked = true;
  }

  public onPreviousClick(): void {
    this.nextClicked = false;
  }
}

And in your component.html

<div>
  <form [formGroup]="form" (ngSubmit)="onSubmit()">
    <input formControlName="age">
    <input formControlName="name">
    <button type="submit" (click)="onNextClick()">Next</button>
    <button type="submit" (click)="onPreviousClick()">Previous</button>
  </form>
</div>

And you can find a working example in this stackblitz.

You can add two separate event handlers for the click events in the two submit buttons. Those event handlers will be triggerd before the onSubmit method. You can use those two event handlers to update a state in the component to identify whether the use clicked on next or previous button.

And depending on that state you can direct the user to diferent pages on onSubmit method.

Rode answered 29/6, 2018 at 9:46 Comment(2)
Great! Simple and obvious! I change to pass a parameter to that function, and I create one handler only. onDoThat(true) or onDoThat(false)Wield
I'd say this is a cleaner solution. The accepted answer which uses the document.activeElement is not purely Angular solution and seems to be a bit hacky for me.Ponzo
C
20

You can try with this solution

component.html

  <form [formGroup]="form" (ngSubmit)="onSubmit(buttonType)">
        <button type="submit" (click)="onSubmit('Next')">Next</button>
        <button type="button" (click)="onSubmit('Previous')">Previous</button>
    </form>

component.ts

onSubmit(buttonType): void {
        if(buttonType==="Next") {
            console.log(buttonType)
        }
        if(buttonType==="Previous"){
            console.log(buttonType)
        }

}
Cabochon answered 29/6, 2018 at 9:55 Comment(2)
this will fire handle twice (once for button click and once for form submit)Esp
indeed we will have two events fired, the form's ngSubmit should be removedSemiweekly
S
6

I found an answer. A bit tricky: In the onSubmit event I check:

var buttonName = document.activeElement.getAttribute("Name");

Since one of the button must be the active element on the form when the user click it, this does the trick for me

Sosthina answered 29/6, 2018 at 9:37 Comment(1)
how to do it in angular?Dessiatine
L
4
<form [formGroup]="CreationForm" (ngSubmit)="onSubmit($event)">  
  <button type="submit" name="draft"> Save As Draft </button>   
  <button type="submit" name="save"> Save </button>
</form>
onSubmit(event) {
  if(event.submitter.name == "draft" ) {
    console.log('draft');
  } else if(event.submitter.name == "save") {
    console.log('save'); }
  }
Latinalatinate answered 22/5, 2020 at 7:44 Comment(0)
J
2

You could add a (click)="buttonClicked='previous/next'" event to the buttons (next/previous as appropriate). Then you have a member variable on your class buttonClicked: string which you read in your onSubmit() method and act as appropriate.

Jubal answered 29/6, 2018 at 9:29 Comment(0)
M
2
<button name="Previous" type="button" [disabled]="form.invalid"> Previous</button>

Just replace the type="submit" to type="button" it wont fire submit event. https://github.com/angular/angular.js/issues/6017

Mnemonic answered 12/9, 2021 at 16:2 Comment(0)
H
0

if you are using wizard it's better to not check validity in Previous step!but if you want to check it you can not use ngsubmit but define your own action:

html:

<button name="Previous" type="submit" (click)="submitForm('pre')"[disabled]="form.invalid"> Previous</button>
<button name="Next" type="submit" (click)="submitForm('next')" [disabled]="form.invalid">Next</button>

in component:

submitForm(type) {
        if (!this.form.valid) {
            this.checkFormValidity();
            return;
        }
    if(type === 'pre'){
      //Redirect one page

}else{
  //Redirect another page
}
}

checkFormValidity() {
        for (let item in this.form.controls) {
            this.form.controls[item].markAsTouched();
        }
    }
Hagan answered 29/6, 2018 at 9:49 Comment(0)
M
0

I solved this with the following solution:

Add a control to the form to store the value you need:

constructor(private fb: FormBuilder) {
   this.form = this.fb.group({
     next: this.fb.control(true) // Set a default value
   });
}

Create a property to easily access the control:

get submitControl(): AbstractControl { return (this.form) ? this.form.get('next') as AbstractControl : undefined; }

Then add your submit buttons to the form, setting the value by handling the click event:

<form novalidate [formGroup]="form" #f="ngForm" (ngSubmit)="onSubmit(f)">
  <button name="Previous" type="submit" [disabled]="form.invalid" (click)="submitControl.patchValue(false)">Previous</button>
  <button name="Next" type="submit" [disabled]="form.invalid" (click)="submitControl.patchValue(true)">Next</button>
</form>

Then you can access the value from the onSubmit handler:

onSubmit(f: FormGroupDirective) {
    console.log(f.value.next);
}
Manille answered 9/2, 2020 at 15:15 Comment(0)
D
-2

try this:

HTML File:

<form [formGroup]="form" (ngSubmit)="onSubmit()">
<button name="Previous" type="submit" (click)="buttonClicked = 'previous'" [disabled]="form.invalid"> Previous</button>
        <button name="Next" type="submit" [disabled]="form.invalid" (click)="buttonClicked = 'next'">Next</button>

TS File:

buttonClicked:string;

    onSubmit() {
        if(buttonClicked == 'previous') {
             //Redirect one page
        } else {
             //Redirect another page
        }
    }
Ditto answered 29/6, 2018 at 9:30 Comment(2)
The previous button could be clicked regardless of if the form is valid or notJubal
do you want one button(previous) cant be clicked if form is not valid?Whiles

© 2022 - 2024 — McMap. All rights reserved.