Home > other >  At least one of the filed is required validation in Angular 11 reactive form
At least one of the filed is required validation in Angular 11 reactive form

Time:09-17

I am using Angular 11 reactive form with below 7 fields.

  • Start Date (Mandatory)
  • End Date (Mandatory)

At least one field is filled

  • phone Number
  • address
  • author
  • user ID
  • company

My form should be valid only if start and end date are selected and among other five fields, at least one field is filled. How can I put this custom validator in my reactive form? Below is my typescript form component.

this.myForm = new FormGroup({
      startDate: new FormControl('', Validators.required),
      endDate: new FormControl('', Validators.required),
    phoneNumber: new FormControl(''),
     address: new FormControl(''),
    author: new FormControl(),
     userID: new FormControl(''),
      company: new FormControl('')
     
    }, { validators: dateValidator }

    );

CodePudding user response:

Here's a basic example of how you're custom validator might look like:

export const atLeastOneValidator = (keys: string[]) => {
  return (group: FormGroup) => {
    const { controls } = group;
    return keys.some(key => controls[key] && !!controls[key].value)
      ? null
      : { atLeastOne: 'error' };
  };
};

And here's how you could use it:

this.myForm = new FormGroup(
      {
        startDate: new FormControl('', Validators.required),
        endDate: new FormControl('', Validators.required),
        phoneNumber: new FormControl(''),
        address: new FormControl(''),
        author: new FormControl(),
        userID: new FormControl(''),
        company: new FormControl('')
      },
      { validators: dateValidator, atLeastOneValidator(['phoneNumber', 'address', 'author', 'userID', 'company']) }
    );

CodePudding user response:

You need 1 of them to exist. Not both of them. So remove Validators.required that you have on both of them

this.myForm = new FormGroup({
      startDate: new FormControl(''),
      endDate: new FormControl(''),
    phoneNumber: new FormControl(''),
     address: new FormControl(''),
    author: new FormControl(),
     userID: new FormControl(''),
      company: new FormControl('')
    });

Then add a customValidator to the form

this.myForm.setValidators(this.atLeastOneFieldValidator())

Then create this validator

public atLeastOneFieldValidator() : ValidatorFn{
       return (group: FormGroup): ValidationErrors => {
          const startDate = group.controls['startDate'];
          const endDate = group.controls['endDate'];
          if (!startDate.value && !endDate.value) {
             startDate.setErrors({atLeastOneError: "startDate or endDate must be filled"});
          } else {
             startDate.setErrors(null);
          }
          return;
    };
 }

Then in your html let this error show when exists only when 1 of those 2 fields has been modified. Not in the start state.

<div>
  <form [formGroup]="myForm">
      ......
    <div *ngIf="( myForm.controls['startDate'].dirty || myForm.controls['startDate'].touched || myForm.controls['endDate'].dirty || myForm.controls['endDate'].touched ) && myForm.controls['startDate'].errors?.atLeastOneError>
       {{myForm.controls['startDate'].errors.atLeastOneError}}
  </form>
</div>

CodePudding user response:

I have used the below code to solve the problem.

this.myForm = new FormGroup(
      {
        startDate: new FormControl('', Validators.required),
        endDate: new FormControl('', Validators.required),
        phoneNumber: new FormControl(''),
        address: new FormControl(''),
        author: new FormControl(),
        userID: new FormControl(''),
        company: new FormControl('')
      },
      { validators: [dateValidator, atLeastOneValidator] }
    );

Validator function :

export const atLeastOneValidator :ValidatorFn=(control: AbstractControl): ValidationErrors | null  => {
    
      if((control.get('phoneNumber')?.value!='')||(control.get('address')?.value!='')
      ||(control.get('author')?.value!='')||(control.get('userID')?.value!='')
      ||(control.get('company')?.value!='')){
        return null;
      }
      else{
        return {atLeastone : 'error'};
      }
     
      
        
   
  };
  • Related