-2

I have several fields to be validated while creating a form in angular this is my code for creating form

 requestForm = this.formBuilder.group({
    requestorName: ['', [Validators.required]],
    requestorEmail: ['', [Validators.required, Validators.email]],
    componentSerialNumber: ['', [Validators.required, Validators.pattern("^[0-9]{5,}$")]],
    componentType: [this.componentTypes[0]],
    //componentId: ['', [Validators.required]],
    macid:['', [Validators.required, Validators.pattern("^.{12}$")]],
    dongleid:['', [Validators.required, Validators.pattern(/^(8-\w{8}|9-\w{10})$/)]],
    vendorid:['', [Validators.required]],
    details: ['']
  });

I macid, dongleid and vendorid are basically types of Components in UI here enter image description here

so I have created individual validators for above component types, is there any way we can group Component Type for validation? meaning if any of macid, dongleid or vendorid is validated the entire form should be considered validated and Submit button gets enabled.

here' html for submit button

<div class="field grid col-12">
            <p-button class="col-1" label="Submit" styleClass="p-button-rounded p-button-warning" (onClick)="onSubmit()"
                [disabled]="!requestForm.valid"
                >
            </p-button>
        </div>

I have tried this way but it is not working

requestForm = this.formBuilder.group({
    requestorName: ['', [Validators.required]],
    requestorEmail: ['', [Validators.required, Validators.email]],
    componentSerialNumber: ['', [Validators.required, Validators.pattern("^[0-9]{5,}$")]],
    componentType: [this.componentTypes[0]],
    //componentId: ['', [Validators.required]],
    macid:['', [Validators.required, Validators.pattern("^.{12}$")]],
    dongleid:['', [Validators.required, Validators.pattern(/^(8-\w{8}|9-\w{10})$/)]],
    vendorid:['', [Validators.required]],
    details: ['']
  }, { validators: this.atLeastOneValidator });

atLeastOneValidator(control: FormGroup): ValidationErrors | null {    
    const macid = control.get('macid')?.valid;
    const dongleid = control.get('dongleid')?.valid;
    const vendorid = control.get('vendorid')?.valid;
  
    if (macid || dongleid || vendorid) {
      console.log("one validated ")
      return null; 
    }
    return { atLeastOneRequired: true };
  };
3
  • you can: disabled the formControls when change the dropdown (remember a formControl disabled is !invalid), e.g. SO, or create a custom validators that take account two controls, e.g. SO, or create a customFormValidator over the whole formGroup link, Commented Dec 18, 2023 at 8:16
  • ..or if you choose your button is always enabled, only show error according the value o the drop down, and in submit, to check if the formGroup is valid, check the individuals FormControls Commented Dec 18, 2023 at 8:16
  • What you tried is a cross form validator, which is fine for your purpose. However, Angular only calls the cross form validator once all controls passed their validity. By putting the required validator on all of your 3 crossform relevant controls, atLeastOneValidator is only called when all 3 have a value and the crossform validator will always return null because of that. Commented Dec 18, 2023 at 9:19

1 Answer 1

1

Disable/Enable:

<select #select formControlName="componentType" (change)="enable(select.value)">
   ...
</select>
....

enable(value:number)
{
   this.requestForm.get('macid')[value==1?'enable':'disable']()
   this.requestForm.get('dongleid')[value==2?'enable':'disable']()
   this.requestForm.get('vendorid')[value==3?'enable':'disable']()
}

Validator that check two controls, based in this another SO

//this allow us check the controls when change the dropdown:

export function checkControls(controlNames:string[])
{
  return (x:AbstractControl) =>
  {
     controlNames.forEach(controlName=>{
        const control=x?.parent?.get(controlName);
        if (control)
             control.updateValueAndValidity()
        }
     })
    return null;
  }
}
export function requireIfValue(controlName:string,value:string)
{
  return (x:AbstractControl) =>
  {
      if (x?.parent?.get(controlName)?.value==value)
      {
          //here check you control, e.g.
          if (!x.value)
             return { required: true }

          if (value=="1") //MAC
             return /^.{12}$/.test(x.value)?null:{pattern:"error"}
             
          if (value=="2") //dongleid
             return /^(8-\w{8}|9-\w{10})$/.test(x.value)?null:{pattern:"error"}

      };
      return null;
  }
}

Now you can define your form like

requestForm = this.formBuilder.group({
    ...
    componentType: [this.componentTypes[0],checkControls(['macid','dongleid','vendorid'],
    macid:['', [requireIfValue('componentType','1')],
    dongleid:['', [requireIfValue('componentType','2')],
    vendorid:['', [requireIfValue('componentType','3')],
    details: ['']
  })
Sign up to request clarification or add additional context in comments.

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.