2

angular v 4.4.3.

In Reactive Form, we can write Validators.required with each form field as below

this.loginForm = this.fb.group({
                firstName: ['', [Validators.required, Validators.maxLength(55)]],
                lastName: ['', Validators.required],
                age: [1, Validators.required],
                email: ['', Validators.required],
                username: ['', Validators.required],
                gender: ['', Validators.required],
                address: this.fb.group({
                    city: ['', Validators.required],
                    country: ['', Validators.required]
                })
            });

Here we need to write Validators.required on each form field.

So I am looking for any solution/method of angular FormBuilder/FormControl which set all field required and can set addition validator on the field if needed.

billyjov
  • 2,778
  • 19
  • 35
xkeshav
  • 53,360
  • 44
  • 177
  • 245
  • good question! - why we cannot go with array and create form controls dynamically? – Var Oct 05 '18 at 05:50
  • but in that case what if i need to add additional Validation for one of field and also if there is formgroup inside a formgroup as i mention in the question. can you give me example how can we do that? – xkeshav Oct 05 '18 at 06:04

3 Answers3

2

You can create a customValidator for the whole form,

this.form = this.fb.group({
  firstName: ['', [Validators.maxLength(55)]],
  ....
},
{
   validator: this.myValidator()
});


myValidator()
{
return (group: FormGroup) => {
    let errors:any={};
    let conError:boolean=false;
    if (!group.value.firstName)
    {
         errors.requiredFirstName=true;
         conError=true;
    }
     ....
    return conError? errors:null
  }
}

//The .html becomes like

<form [formGroup]="form " (ngSubmit)="onSubmit()">
    <div class="form-group">
         <label for="firstName">UserName</label>
         <input type="text" class="form-control"
             id="firstName" formControlName = "firstName">
     <!--see that we ask about form?.errors?requiredFirsName 
          requiredFirsName is the property we add to errors
         we add the condition is touched too 
         because else, at first, Angular show the error-->
             <span class="help-block" *ngIf="form?.errors?.requiredFirstName && 
     form.get('firstName').touched ">First Name required</span>
    </div>
    ....
   <!--just for check -->
   {{form?.errors |json}}
</form>
Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • Thank you for suggesting this approach and how do we write to display the error in HTML? we have a form where the error comes under the form field. does `formName.controls['firstName].required` will catch this error or this is a async Validator. please clear more. – xkeshav Oct 05 '18 at 09:20
  • 1
    Only for check, write in your .html {{loginForm?.errors|json}} and see the values. Then the error can be showhed by *ngIf="loginForm.errors.requiredFirst && ..." – Eliseo Oct 05 '18 at 09:47
  • will you please add the HTML snippet too. – xkeshav Oct 07 '18 at 09:17
  • added a brief html. see that I wrote requiredFirsName, I change to requiredFirstName – Eliseo Oct 08 '18 at 07:07
0

You can write a function to deep iterate over FormGroup and FormArray:

deepIterate(control: FormGroup | FormArray, iteratee: (control) => void): void {
    _.forEach(control.controls, control => {
        if (control instanceof FormControl) {
            iteratee(control);
        } else if (control instanceof FormGroup || control instanceof FormArray) {
            FormUtils.deepIterate(control, iteratee);
        }
    });
}

Now to add required validator to each FormControl you can use this function:

addRequiredValidators(control: FormGroup | FormArray): void {
    deepIterate(
        control,
        (control) => control.setValidators(Validators.compose([Validators.required, control.validator]))
    );
}

You can call addRequiredValidators after you create your FormGroup.

Ludevik
  • 6,954
  • 1
  • 41
  • 59
0

go with clean approach.

[{
  "firstname": ""
  "required": "true/false",
  "pattern" :""
},
{
  "lastname": ""
  "required": "true/false",
  "pattern" :""
}]

create array with required fields/ sub fields. do the for each loop over this array and create form controls.

For example : How to add dynamically FormControl to FormGroup

OR if you care only for Validator.required - then @Ludevik's answer is best option, but it will be extra work for angular - first you're define forms controls then you're define Validator.required

Var
  • 270
  • 1
  • 5
  • 23