1

I am sure this is simple. I have this html:

<form [formGroup]="formGroup">
    <mat-form-field class="form-group" appearance="outline">
        <mat-label>Choose your start date</mat-label>
        <input matInput formControlName="startDate" aria-label="startDate"
            [matDatepicker]="start">
        <mat-datepicker-toggle matSuffix [for]="start"></mat-datepicker-toggle>
        <mat-datepicker #start></mat-datepicker>
    </mat-form-field>

    <mat-form-field class="form-group" appearance="outline">
        <mat-label>End date</mat-label>
        <input matInput formControlName="endDate" aria-label="endDate" [matDatepicker]="end">
        <mat-datepicker-toggle matSuffix [for]="end"></mat-datepicker-toggle>
        <mat-datepicker #end></mat-datepicker>
    </mat-form-field>

    <div class="form-group">
        <mat-slide-toggle formControlName="rolling">Continue until further notice?
        </mat-slide-toggle>
    </div>
</form>

I am trying to only enable the endDate if the rolling is toggled off.

I have tried doing it like this:

public formGroup: FormGroup;
public subscription: Subscription;

// convenience getter for easy access to form fields
get f() {
  return this.formGroup.controls;
}

constructor(
  private formBuilder: FormBuilder
) {}

ngOnInit(): void {
  this.createForm();
}

private createForm(): void {
  this.formGroup = this.formBuilder.group({
    startDate: new FormControl(
      this.subscription.startDate,
      Validators.required
    ),
    rolling: this.subscription.rolling,
  });
  this.formGroup.addControl(
    'endDate',
    new FormControl({
      value: this.subscription.endDate,
      disabled: this.f.rolling.value === true,
    })
  );
}

But when I toggle the slider, nothing happens. The input is always disabled. Does anyone know why?

2

2 Answers 2

2

Example reproduced and resolved at: https://stackblitz.com/edit/angular-ivy-h4wyta?file=src/app/app.component.ts

disabled: this.f.rolling.value === true

Simply this won't work. You have to detect the changes on toggle.

First of all simplify the form initialization.

this.formGroup = this.formBuilder.group({
   startDate: new FormControl(this.testObject.startDate, Validators.required),
   endDate: new FormControl(this.testObject.endDate, Validators.required),
   rolling: this.testObject.rolling
});

And there is two ways to resolve the issue.

  1. Subscribe to FormControl's valueChanges event.
  2. Subscribe to MatSlideToggle's OnChange event.

Way 1:

this.formGroup.get("rolling").valueChanges.subscribe(value => {
   this.rollingChanged(value);
});

Way 2:

onChange() {
   const value = this.formGroup.get("rolling").value;
   this.rollingChanged(value);
}

Then you have to do the disable work.

rollingChanged(value: boolean) {
    const control = this.formGroup.get("endDate");
    if (value) {
      control.reset();
      control.clearValidators();
      control.disable();
    } else {
      control.enable();
      control.setValidators([Validators.required]);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Also creating a class or interface can be used easily avoiding rxjs Subscriptions.
0

As rolling is part of the form, you could write like below and try:

this.formGroup = this.formBuilder.group({
    startDate: new FormControl(
      this.subscription.startDate,
      Validators.required
    ),
    rolling: new FormControl(this.subscription.rolling)
  });

I think you forgot to mention the new FormControl() for rolling.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.