1

So I'm using angular 11 and struggling to get the following behavior : A stepper, with two inputs in a single steps, that are a datepicker and a select (a dropdown menu). Then I want the stepControl to validate that both fields have been filled, and be able to retrieve their values.

In my example I have many steps, but here is the one that give me troubles.

HTML :

<mat-vertical-stepper>

   <!-- First steps... -->

   <mat-step state="date" [stepControl]="fourthFormGroup">
       <form [formGroup]="fourthFormGroup">
         <mat-form-field>
           <ng-template matStepLabel>Placeholder Text Date</ng-template>
           <input matInput [min]="minDate" [matDatepicker]="picker" [formControl]="date">
           <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
           <mat-datepicker #picker></mat-datepicker>
         </mat-form-field>

         <br/>

         <mat-form-field>
           <mat-label>Placeholder Text Hour</mat-label>
            <mat-select [formControl]="hours" required>
             <mat-option *ngFor="let j of hours" [value]="j[0]">
               {{j[1]}}
             </mat-option>
           </mat-select>
         </mat-form-field>
       </form>
       <div>
         <button mat-button matStepperPrevious>Back</button>
         <button mat-button (click)="searchNow()">Search</button>
        </div>
     </mat-step>

</mat-vertical-stepper>

TS declaration :

public fourthFormGroup: FormGroup;

TS in ngOnInit :

this.fourthFormGroup = this._formBuilder.group({
  date: new FormControl(new Date()),
  hours: new FormControl('', Validators.required)
});

Why it doesn't work :

I am unable to retrieve the values from this form. Also, validating the form with empty fields generate backend error but is not prevented by the frontend-component as you would expect it (to light up in the red and say the field is required).

Many thanks for your help ! Kev'.

Kevin Heirich
  • 109
  • 2
  • 12
  • Can you share a demo on stackblitz? I think you have over complicated your code and this can be made simpler with the same functionality – Owen Kelvin Feb 12 '21 at 10:15
  • Hey there ! Well it's really weird, I have errors in my stackblitz demo that I don't in my dev' environment. Here it is : https://stackblitz.com/edit/angular-vxj7qy?file=src/app/stepper-vertical-example.ts It doesn't work for now but that is what i am running now, and I am really struggling making the forms work or understand how they work inside a stepper. I am trying to make a stackblitz working version. – Kevin Heirich Feb 12 '21 at 10:44

1 Answers1

0

The Problem you are facing is that you are mixing the directives. You are binding a [FormControl] to undefined values e.g [formControl]='date' will definitely not work.

Change [formControl]='date' to formControlName='date' and formControl="hours" to formControlName="hours"

See this demo

NB

I believe a better approach would simply to have one formGroup for all your inputs

  myForm = this.formBuilder.group({
    thirdFormControl: ['', [Validators.required]],
    date: [new Date(), [Validators.required]],
    hours: ["", [Validators.required]]
  })

And amend your html

<form [formGroup]='myForm'>
    <mat-vertical-stepper [linear]="true" #stepper>
        <mat-step [stepControl]="step[0]" [optional]="true">

            <ng-template matStepLabel>Placeholder title</ng-template>
            <mat-form-field>
                <mat-label>Placeholder label</mat-label>
                <textarea
          matInput
          cdkTextareaAutosize
          #autosize="cdkTextareaAutosize"
          cdkAutosizeMinRows="2"
          cdkAutosizeMaxRows="10"
          placeholder="Optionnel"
          formControlName="thirdFormControl"
        ></textarea>
            </mat-form-field>
            <div>
                <button mat-button matStepperPrevious>Back</button>
                <button mat-button matStepperNext>Next</button>
            </div>
        </mat-step>

        <mat-step state="date" [stepControl]="step[1]">
            <mat-form-field>
                <ng-template matStepLabel>Placeholder label 0</ng-template>
                <input
          matInput
          [min]="minDate"
          [matDatepicker]="picker"
          formControlName="date"
        />
                <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
                <mat-datepicker #picker></mat-datepicker>
            </mat-form-field>

            <br />

            <mat-form-field>
                <mat-label>Placeholder label 1</mat-label>
                <mat-select formControlName="hours" required>
                    <mat-option *ngFor="let j of hours" [value]="j[0]">
                        {{j[1]}}
                    </mat-option>
                </mat-select>
            </mat-form-field>
            <div>
                <button mat-button matStepperPrevious>Back</button>
                <button mat-button (click)="searchNow()">Search</button>
            </div>
        </mat-step>
    </mat-vertical-stepper>
</form>

Now the form will be invalid if any of the inputs is not captured

Sample Here

Owen Kelvin
  • 14,054
  • 10
  • 41
  • 74
  • Hey there ! Thanks for your answer. Well on theory your idea seem well better code wise, but I think that does allow the user to skip steps. Even if in the end you can check that the form is invalid. Please see [this demo](https://stackblitz.com/edit/angular-vxj7qy-zgwhzq?file=src/app/stepper-vertical-example.html) where i add a mandatory select at the beginning. Even if the result is that the form is invalid due to the control, the user can fill steps 2 and 3 without step 1 and i don't want that because some of my steps will be filled dynamicly depending on first steps. – Kevin Heirich Feb 15 '21 at 08:38
  • However the use of formControlName allows be to solve my problem. I don't know if it is the cleanest way of cleaning but that will do ! Many thanks for your answer ! It helped a lot ! – Kevin Heirich Feb 15 '21 at 08:45
  • Great it helped! – Owen Kelvin Feb 15 '21 at 08:48