Angular 2: Add validators to ngModelGroup

前端 未结 3 893
被撕碎了的回忆
被撕碎了的回忆 2021-01-13 23:08

I am using a ngModelGroup directive to group several form inputs together.

In the docs (https://angular.io/docs/ts/latest/api/forms/index/NgModelGroup-d

相关标签:
3条回答
  • 2021-01-13 23:22

    Looks like each control in your ModelGroup should have is own validator. once this is done you might have access to each one through the validators array. so add the required attribute to the inputs that are required

    0 讨论(0)
  • 2021-01-13 23:23

    Thanks all for helping me out! I've accepted Silentsod's answer because it was most helpful.

    My final solution was simply building the form using FormBuilder.

    In my component, create the form and add the validator function to it:

    ngOnInit(): void {
        // Validator function:
        let validateMemberList = (group: FormGroup) => {
            let checked = Object.keys(group.controls).reduce((count, key: string) => {
                return count + (group.controls[key].value ? 1 : 0);
            }, 0);
    
            return checked === 0 ? {'minchecked': 1} : null;
        };
    
        this.jobForm = this.formBuilder.group({
            jobTitle: ['', Validators.required],
            // more inputs...
            members: this.formBuilder.group({}, {
                // The 2nd argument is an object with a validator property:
                validator: validateMemberList
            }),
            supportMembers: this.formBuilder.group({}, {
                validator: validateMemberList
            })
        });
    

    Then in my template:

    <form [formGroup]="jobForm">
        <ul formGroupName="members">
            <li *ngFor="let user of teamMembers.members">
                <label class="e-label">
                    <input class="e-input" type="checkbox" [formControlName]="user.$key">
                    <user-badge [user]="user"></user-badge>
                </label>
            </li>
        </ul>
    ...
    

    This validates the form allowing me to display errors and disable the submit button.

    Thanks all for the help!

    0 讨论(0)
  • 2021-01-13 23:36

    This is entirely possible with a ngModelGroup and a custom directive for validation. Key to understanding why this works is that ngModelGroup

    Creates and binds a FormGroup instance to a DOM element.

    First, we'll build out our directive which is pretty boilerplate with nothing special going on:

    @Directive({
      selector: '[hasRequiredCheckboxInGroup]',
      providers: [{provide: NG_VALIDATORS, useExisting: HasRequiredCheckBoxInGroup, multi: true}]
    })
    export class HasRequiredCheckBoxInGroup implements Validator, OnChanges {
      private valFn = Validators.nullValidator;
    
      constructor() {
        this.valFn = validateRequiredCheckboxInGroup();
      }
    
      validate(control: AbstractControl): {[key: string]: any} {
        return this.valFn(control);
      }
    }
    

    Our validation function is where we take our key knowledge that ngModelGroup creates a FormGroup and apply it:

    function validateRequiredCheckboxInGroup() : ValidatorFn {
          return (group) => { //take the group we declare in the template as a parameter
            let isValid = false; //default to invalid for this case
            if(group) {
              for(let ctrl in group.controls) {
                if(group.controls[ctrl].value && typeof group.controls[ctrl].value === 'boolean') { // including a radio button set might blow this up, but hey, let's be careful with the directives
                  isValid = group.controls[ctrl].value;
                }
              }
            }
    
            if(isValid) {
              return null;
            } else {
              return { checkboxRequired: true };
            }
          }
        }
    

    And finally, having included and declared in our Module the directive, we return to the template (needs to be in a form):

    <form #f="ngForm">
          <div ngModelGroup="checkboxes" #chks="ngModelGroup" hasRequiredCheckboxInGroup>
              <input type="checkbox" name="chk1" [(ngModel)]="checks['1']"/>
              <input type="checkbox" name="chk2" [(ngModel)]="checks['2']"/>
          </div>
          <div>
          {{chks.valid}}
          </div>
    </form>
    

    And here's a plunker with all this available to play with: http://plnkr.co/edit/AXWGn5XwRo60fkqGBU3V?p=preview

    0 讨论(0)
提交回复
热议问题