Search code examples
angularangular7angular-material-stepper

Angular Material Vertical Stepper single form .reset() not functioning correctly


I've been working on a stepper element for one of my web pages and have tried to implement the .reset() functionality in order to revert the form to a blank state using the material design documentation (https://material.angular.io/components/stepper/overview)

Following the multiple form group example, I can see that .reset works correctly by putting you back to the first step and clearing the form. However, upon trying to use the single form structure, I've found that stepper.reset() brings you back to the first step but doesn't clear the form.

I've tried labeling the reset button as Type="button" since single forms require that on the Next and Back buttons to prevent form submission on button click but haven't seen any change.

I'd like both actions to occur when reset is clicked, but I'm unsure if I'll have to write a manual reset function or if I just have a bug in my code.

Any help with this would be much appreciated. Thanks!

create.component.html

<form [formGroup]="formGroup" class="content-container" (ngSubmit)="onSubmit()">
  <h1>{{title}}</h1>
  <mat-vertical-stepper #stepper>
    <mat-step formGroupName="someFieldGroup" [stepControl]="someFieldGroup">
      <ng-template matStepLabel>Fill out Field</ng-template>
      <mat-form-field>
        <input matInput placeholder="Some Field" formControlName="someFieldCtrl" name="someFieldName" required>
        <mat-error>This field is required</mat-error>
      </mat-form-field>
      <div>
        <button type="button" mat-button matStepperNext>Next</button>
      </div>
    </mat-step>
    <mat-step formGroupName="anotherFieldGroup" [stepControl]="anotherFieldGroup">
      <ng-template matStepLabel>Fill out Field</ng-template>
      <mat-form-field>
        <input matInput placeholder="Another Field" formControlName="anotherFieldCtrl" name="anotherFieldName" required>
        <mat-error>This field is required</mat-error>
      </mat-form-field>
      <div>
        <button type="button" mat-button matStepperPrevious>Back</button>
        <button type="button" mat-button matStepperNext>Next</button>
      </div> 
    </mat-step>
    <mat-step formGroupName="dropdownFieldGroup" [stepControl]="dropdownFieldGroup">
      <ng-template matStepLabel>Select Option</ng-template>
      <mat-form-field>
        <mat-select placeholder="Select Option" disableOptionCentering formControlName="dropdownFieldCtrl" name="dropdownFieldName" required>
          <mat-option value="1">One</mat-option>
          <mat-option value="2">Two</mat-option>
          <mat-option value="3">Three</mat-option>
          <mat-option value="4">Four</mat-option>
        </mat-select>
        <mat-error>This field is required</mat-error>
      </mat-form-field>
      <div>
        <button type="button" mat-button matStepperPrevious>Back</button>
        <button type="button" mat-button matStepperNext>Next</button>
      </div>
    </mat-step>
    <mat-step>
      <ng-template matStepLabel>Done</ng-template>
      You are now done.
      <div>
        <button type="button" mat-button matStepperPrevious>Back</button>
        <button type="submit" mat-button>Done</button>
        <button mat-button (click)="stepper.reset()">Reset</button>
      </div>
    </mat-step>
  </mat-vertical-stepper>
</form>

create.component.ts

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

//Type Imports
import { Service } from '../service';
import { Post } from './post';

@Component({
  selector: 'app-create',
  templateUrl: './create.component.html',
  styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit {

  title = 'Create';

  formGroup: FormGroup;
  post: Post = {} as Post;

  constructor(private service: Service) { }

  ngOnInit() {
    this.formGroup = new FormGroup({
      someFieldGroup: new FormGroup({
        someFieldCtrl: new FormControl(null)
      }),
      anotherFieldGroup: new FormGroup({
        anotherFieldName: new FormControl(null)
      }),
      dropdownFieldGroup: new FormGroup({
        dropdownFieldCtrl: new FormControl(null)
      })
    });
  }

  onSubmit() {
    this.post.someField = this.formGroup.get('someFieldGroup').get('someFieldName').value;
    this.post.anotherField = this.formGroup.get('anotherFieldGroup').get('anotherFieldName').value;
    this.post.dropdownField = this.formGroup.get('dropdownFieldGroup').get('dropdownFieldName').value;

    this.service.create(JSON.stringify(this.post)).subscribe(data => { console.log(data) });
  }
}

Solution

  • I was facing this issue as well. Calling reset on the stepper seems to only position you back at the first step. If you also call reset on the form itself, then the form fields should clear.

    Example:

    <form [formGroup]="formGroup" class="content-container" (ngSubmit)="onSubmit() 
    #myFormGroup">
    ...
      <button mat-button (click)="myFormGroup.reset();stepper.reset()">Reset</button>
          </div>
        </mat-step>
      </mat-vertical-stepper>
    </form>