AbstractControl.value[data] is retuning undefined in Custom Validator using AbstractControl?

545 Views Asked by At

I'm trying to write cross-field -validation using Abstract Control. control.value[start] is showing undefined. kindly help me on solving. working code is here.

app.component.html

export class AppComponent {
  form: FormGroup;
  rangeStart = new FormControl('', {
    validators: [this.MyAwesomeRangeValidator('rangeStart')],
  });
  rangeEnd = new FormControl('', {
    validators: this.MyAwesomeRangeValidator('rangeEnd'),
  });
  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      rangeStart: this.rangeStart,
      rangeEnd: this.rangeEnd,
    });
  }

  MyAwesomeRangeValidator(rangeStart: string): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      const start = control.value[rangeStart];
      const end = control.value;
      console.log('start', start, 'end', end);
      let re = /^[1-9]\d*$/;
      if (re.test(start) && re.test(end)) {
        return null;
      } else if (re.test(start) && !re.test(end)) {
        return null;
      } else if (!re.test(start) && re.test(end)) {
        return null;
      } else {
        return {
          range: true
        };
      }
    };
  }
}
<form [formGroup]="form">
  <input formControlName="rangeStart" placeholder="Range start" type="number">
  <input formControlName="rangeEnd" placeholder="Range end" type="number">
</form>
<div> Valid: {{ form.valid ? '' : '' }} </div>

working code

1

There are 1 best solutions below

5
bam On

You are trying to get property 'rangeStart' from string.

const start = control.value[rangeStart];, where control.value is a string. If you want to validate few fields at once then you should put validator to the FormGroup.

export class AppComponent {
  form: FormGroup;
  rangeStart = new FormControl('', {
    validators: [this.MyAwesomeRangeValidator('rangeStart', 'rangeEnd')],
  });

  rangeEnd = new FormControl('', {
    validators: this.MyAwesomeRangeValidator('someField_1', 'someField_2'),
  });

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      rangeStart: this.rangeStart,
      rangeEnd: this.rangeEnd,
    });
  }

  MyAwesomeRangeValidator(
    startControlName: string,
    endControlName: string
  ): ValidatorFn {
    return (formGroup: FormGroup): ValidationErrors | null => {
      const start = formGroup.get(startControlName).value;
      const end = formGroup.get(endControlName).value;

      console.log(formGroup, 'start', start, 'end', end);

      let re = /^[1-9]\d*$/;

      if (!re.test(start) && !re.test(end)) {
        return { range: true };
      }

      return null;
    };
  }
}

UPD: added dynamic form controls names