[問題]動態的連動驗證

各位前輩好,最近在做一個動態表單的專案在驗證的部分卡了很久,想問問各位,
要怎麼做到當頁面上有多個checkbox時,輸入框必須勾選特定的checkbox才會被驗證為必填?

這個可以透過 reactive form 的 formControl valuechange 來設定其他 control 的驗證條件

kevin大,安安,感謝你的回覆,目前有遇到個問題是,我用FormArray來裝checkbox的FormControl物件,FormArray有一個自訂的驗證器,是用來驗證checkbox至少勾選一個,不過當我在表單頁勾選特定的checkbox時,輸入框必須要在上面打一些字再刪掉,才會有驗證必填的效果。
想請教kevin大,是不是哪邊出錯了才會導致這個現象

以下是我的code

question-control.service.ts

import {Injectable} from '@angular/core';
import {AbstractControl, FormArray, FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';
import {QuestionBase} from '../../health/model/question-base';
import {forEach} from '@angular/router/src/utils/collection';
import {CheckboxValidate} from '../../health/validator/checkbox-validation';

@Injectable()
export class QuestionControlService {

    constructor(public fb: FormBuilder) {
    }

    toFormGroup(questions: QuestionBase<string>[]): FormGroup {
        let group: any = {};

        questions.forEach(question => {
            // initFormAry = this.buildFormArray(question.options.length);
            switch (question.controlType) {
                case 'checkbox':
                    group[question.key] = this.buildFormArray(question);
                    break;
                case 'CATSuffix':
                    group[question.key] = this.buildFormArray(question);
                    break;
                default:
                    group[question.key] = question.required
                        ? new FormControl(question.value || '', Validators.required)
                        : new FormControl(question.value || '');
                    break;
            }
        });
        return new FormGroup(group);
    }

    buildFormArray(ques: any): AbstractControl {
        let tmpFormArray: Array<any> = [];
        for (let i = 0; i <= ques.options.length; ++i) {
                tmpFormArray.push(new FormControl(''));
        }
        return new FormArray(tmpFormArray, this.ckbValidators);
    }

    ckbValidators(formArray: FormArray) {
        let trueCount = 0;
        for (let i = 0; i < formArray.length; ++i) {
            if (formArray.controls[i].value === true) {
                trueCount++;
            }
        }
        if (trueCount < 1) {
            return {ckbValidate: true};
        } else {
            return null;
        }
    }
}

dynamic-form-question.component.ts

import {Component, OnInit, Input, OnChanges} from '@angular/core';
import {AbstractControl, AsyncValidator, Form, FormGroup, Validators} from '@angular/forms';
import {QuestionBase} from '../../../health/model/question-base';
import {isNullOrUndefined} from 'util';

@Component({
    selector: 'app-dynamic-form-question',
    templateUrl: './dynamic-form-question.component.html',
    styleUrls: ['./dynamic-form-question.component.css']
})
export class DynamicFormQuestionComponent implements OnInit {
    @Input() question: any;
    @Input() form: FormGroup;


    constructor() {

    }

    ngOnInit() {
        // console.log(this.form.controls['Q004'].valid);
        this.onChange();
    }

    get isValid() {
        return this.form.controls[this.question.key].valid;
    }

    onChange(): void {
        this.form.get('Q004.6').valueChanges.subscribe(val => {
            if (val === true) {
                this.form.get('Q004.7').setValidators(Validators.required);
            } else {
                this.form.get('Q004.7').clearValidators();
            }
        });
    }
}

你需要在執行這一個方法 updateValueAndValidity

https://angular.io/api/forms/AbstractControl#updateValueAndValidity

4個讚

Kevin大,謝謝你的指教