0

Scenario: I have 4 form fields.

  1. Description (Optional)
  2. Select Type (Required)
  3. Phone (Required only if Select Type is set to 'Phone')
  4. Email (Required only if Select Type is set to 'Email')

When I change anything is Select Type field, based on the selection, Phone field or Email field will be visible. I need to validate these fields.

Problem:

When the form loads, it'll have only description, select type dropdown and save button.

Step 1: Click save button without entering any input, should throw an alert saying Select Type is required and select type will be red.

Step 2: Select a type, the next input becomes visible with red border. This should not happen since the user didn't touched the field. How can I solve this?

Code:

Stackblitz code

html

<div class="example-container">
    <form [formGroup]="groupForm" (ngSubmit)="onSubmit()">
        <section>
            <section class="input-row">
                <mat-form-field>
                    <input matInput type="test" placeholder="Description" id="description" formControlName="description"/>
        </mat-form-field>
            </section>
            <section class="input-row">
                <mat-form-field>
                    <mat-select id="sourceType" formControlName="sourceType" placeholder="Select Type*">
                        <mat-option value="phone">Phone</mat-option>
                        <mat-option value="email">Email</mat-option>
                    </mat-select>
                </mat-form-field>
            </section>
            <section *ngIf="typeIsPhone" class="input-row">
                <mat-form-field>
                    <input matInput type="number" placeholder="Phone" id="phoneValue" formControlName="phoneValue"/>
        </mat-form-field>
            </section>
            <section *ngIf="typeIsEmail" class="input-row">
                <mat-form-field>
                    <input matInput type="email" placeholder="Email" id="emailValue" formControlName="emailValue"/>
        </mat-form-field>
            </section>
        </section>
        <button mat-raised-button color="primary" type="submit" class="save">
      Save
    </button>
    </form>
</div> 

component:

export class FormFieldOverviewExample implements OnInit {
  typeIsPhone = false;
  typeIsEmail = false;
  public groupForm: FormGroup = new FormGroup({
    description: new FormControl(""),
    sourceType: new FormControl("", [Validators.required]),
    phoneValue: new FormControl("", [Validators.required]),
    emailValue: new FormControl("", [Validators.required])
  });

  constructor() {}

  ngOnInit(): void {
    this.groupForm
      .get("sourceType")
      .valueChanges.subscribe(this.setSourceType.bind(this));
  }

  setSourceType(SourceType: string) {
    this.typeIsPhone = SourceType === "phone";
    this.typeIsEmail = SourceType === "email";
  }

  onSubmit() {
    const sourceTypeFormControl = this.groupForm.get("sourceType");
    const phoneEnteredFormControl = this.groupForm.get("phoneValue");
    const emailEnteredFormControl = this.groupForm.get("emailValue");

    if (sourceTypeFormControl.errors.required) {
      alert("Source Type is required!");
      return;
    } else {
      if (phoneEnteredFormControl.errors.required) {
        alert("Phone is required!");
        return;
      }
      if (emailEnteredFormControl.errors.required) {
        alert("email is required!");
        return;
      }
    }
  }
}
3
  • You can check whether user changed formControl value with its pristine property Commented Mar 3, 2020 at 6:23
  • I tried using markaspristine and markasuntouched. still the field is showing as red Commented Mar 3, 2020 at 6:28
  • Just check whether formControl is pristine and show error if it is and is invalid. Commented Mar 3, 2020 at 6:31

2 Answers 2

1

As if a FormControl is disabled don't has errors I suggest another aproach using disable and enable that you can see in this stackblitz

ngOnInit(): void {
    const control=this.groupForm.get("sourceType")
    if (control)
       control.valueChanges.pipe( //Use startWith to execute at first
             startWith(control.value)
       ).subscribe(res=>this.setSourceType(res)); //<--see how pass the value
  }

  setSourceType(SourceType: string) {
    this.typeIsPhone = SourceType === "phone";
    this.typeIsEmail = SourceType === "email";
    const phoneControl=this.groupForm.get('phoneValue')
    const emailControl=this.groupForm.get('emailValue')
    if (phoneControl) 
      phoneControl[SourceType==='phone'?'enable':'disable']() //(*)
    if (emailControl)
      emailControl[SourceType==='email'?'enable':'disable']()
  }
  //(*) is a abreviated way to say 
  //             if (SourceType=='phone')
  //                phoneControl.enable()
  //             else
  //                phoneControl.disable()

NOTE:

  //You can not use 
  if (phoneEnteredFormControl.errors.required) //WRONG
  //use 
  if (phoneEnteredFormControl.errors && phoneEnteredFormControl.errors.required) //OK
Sign up to request clarification or add additional context in comments.

6 Comments

I should not disable the save button. any error should be reported after hitting the save button.
then, remove [disabled]="groupForm.invalid" from button , it was only an example
But still I'm getting that red border without touching phone formcontrol
well if you get out the button from the form, I think work according your requeriments. I updated the stackblitz
Now I'm not even getting the reb border if the field is invalid. First clicking save button without any type gives me an error alert and the source type will be red. Then If i select Phone, the phone form element will be visible, now the phone also has red border. I wish to remove that red border, because the user didn't touched that element.
|
0

The problem stems from the submitted property, the button with implied type=submit, and the way the default ErrorStateMatcher handles this case.

Maybe use

type="button" (click)="onSubmit()"

1 Comment

I tried that, in this case. The alert is triggering but the red border is not applied even if the formcontrol is invalid

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.