动态 FormControl 验证

Dynamic FormControl Validation

我有一个表单控件,它是通过带有索引的 ngFor 生成的。

   <input formControlName='answerControl{{i}}' type="textbox" name="" value="{{ question.answer }}">

如果最小长度不是 4,我如何向这个特定的 formControl 添加验证。

在我的组件中我有:

 this.answer_0 = new FormControl(this.questionsArr[0][2], Validators.minLength(4));

当我尝试时:

 <div *ngIf="answerControl{{i}}.valid">Error</div>

我遇到错误,无法完成。

完整的 TS 代码:

    @Component({
  selector: 'app-fp-edit-pvq',
  templateUrl: './fp-pvq.component.html',
  animations: [
    trigger('hideShow', [
      state('hide', style({
        opacity: 0,
        height: 0
      })),
      state('show', style({
        opacity: 1,
        height: '*'
      })),
      transition('hide => show', animate('150ms ease-in')),
      transition('show => hide', animate('150ms ease-out'))
    ])
  ]

})
export class FpPVQ implements OnInit {
    constructor( private _pvqStepUp: PVQStepUpService, private _langToggle: ErrorToggleService ) { }
    private questions: any;
    private lang: string;
    private counter: number = 0;
    private checkedLimit: number = 5;
    private updateMode: boolean = false;
    private createMode: boolean = false;
    private deadlinePassed: boolean = false;
    private pvqForm:FormGroup;
    private answer_0:FormControl;
    private answer_1:FormControl;
    private answer_2:FormControl;
    private answer_3:FormControl;
    private answer_4:FormControl;
    private answer_5:FormControl;
    private answer_6:FormControl;
    private answer_7:FormControl;
    private answer_8:FormControl;
    private answer_9:FormControl;
    private answer_10:FormControl;
    private answer_11:FormControl;
    private answer_12:FormControl;
    private answer_13:FormControl;
    private answer_14:FormControl;
    private answer_15:FormControl;
    private answer_16:FormControl;
    private answer_17:FormControl;
    private answer_18:FormControl;
    private answer_19:FormControl;
    private answerControlArr: Array<FormControl> = [];
    private questionsArr: Array<any> = [];


  ngOnInit() {
    this.lang = document['locale'];
    console.log('fpPVQ:: pvqStepUpData --> {}, ', this._pvqStepUp.data);
    if(this._pvqStepUp.data != null){
      this.questions = this._pvqStepUp.data.pvqs; 
      this.questions.forEach(object => {
        this.questionsArr.push([object.question_EN, object.question_FR, object.answer]);
      })
      if(this._pvqStepUp.data.deadlinePassed)
        this.deadlinePassed = true;
    }

        this.answer_0 = new FormControl(this.questionsArr[0][2], Validators.required);
        this.answer_1 = new FormControl(this.questionsArr[1][2], Validators.required);
        this.answer_2 = new FormControl(this.questionsArr[2][2], Validators.required);
        this.answer_3 = new FormControl(this.questionsArr[3][2], Validators.required);
        this.answer_4 = new FormControl(this.questionsArr[4][2], Validators.required);
        this.answer_5 = new FormControl(this.questionsArr[5][2], Validators.required);
        this.answer_6 = new FormControl(this.questionsArr[6][2], Validators.required);
        this.answer_7 = new FormControl(this.questionsArr[7][2], Validators.required);
        this.answer_8 = new FormControl(this.questionsArr[8][2], Validators.required);
        this.answer_9 = new FormControl(this.questionsArr[9][2], Validators.required);
        this.answer_10 = new FormControl(this.questionsArr[10][2], Validators.required);
        this.answer_11 = new FormControl(this.questionsArr[11][2], Validators.required);
        this.answer_12 = new FormControl(this.questionsArr[12][2], Validators.required);
        this.answer_13 = new FormControl(this.questionsArr[13][2], Validators.required);
        this.answer_14 = new FormControl(this.questionsArr[14][2], Validators.required);
        this.answer_15 = new FormControl(this.questionsArr[15][2], Validators.required); 
        this.answer_16 = new FormControl(this.questionsArr[16][2], Validators.required);
        this.answer_17 = new FormControl(this.questionsArr[17][2], Validators.required);
        this.answer_18 = new FormControl(this.questionsArr[18][2], Validators.required);
        this.answer_19 = new FormControl(this.questionsArr[19][2], Validators.required);

        this.answerControlArr.push(this.answer_0);
        this.answerControlArr.push(this.answer_1);
        this.answerControlArr.push(this.answer_2);
        this.answerControlArr.push(this.answer_3);
        this.answerControlArr.push(this.answer_4);
        this.answerControlArr.push(this.answer_5);
        this.answerControlArr.push(this.answer_6);
        this.answerControlArr.push(this.answer_7);
        this.answerControlArr.push(this.answer_8);
        this.answerControlArr.push(this.answer_9);
        this.answerControlArr.push(this.answer_10);
        this.answerControlArr.push(this.answer_11);
        this.answerControlArr.push(this.answer_12);
        this.answerControlArr.push(this.answer_13);
        this.answerControlArr.push(this.answer_14);
        this.answerControlArr.push(this.answer_15);
        this.answerControlArr.push(this.answer_16);
        this.answerControlArr.push(this.answer_17);
        this.answerControlArr.push(this.answer_18);
        this.answerControlArr.push(this.answer_19);

         this.pvqForm = new FormGroup({ 

                                        answerControl0: this.answer_0,
                                        answerControl1: this.answer_1,
                                        answerControl2: this.answer_2,
                                        answerControl3: this.answer_3,
                                        answerControl4: this.answer_4,
                                        answerControl5: this.answer_5,
                                        answerControl6: this.answer_6,
                                        answerControl7: this.answer_7,
                                        answerControl8: this.answer_8,
                                        answerControl9: this.answer_9,
                                        answerControl10: this.answer_10,
                                        answerControl11: this.answer_11,
                                        answerControl12: this.answer_12,
                                        answerControl13: this.answer_13,
                                        answerControl14: this.answer_14,
                                        answerControl15: this.answer_15,
                                        answerControl16: this.answer_16,
                                        answerControl17: this.answer_17,
                                        answerControl18: this.answer_18,
                                        answerControl19: this.answer_19

                                   });

      this.questions.sort((a,b) => {
        //This sorts all the entries 
        if(a.answer > b.answer) return -1;
      });

    //Determine if Update or Create
    if(this._pvqStepUp.data.flow !== 'CREATE'){
      this.createMode = true;
      this.counter = 0;
    } else {
      this.updateMode = true;
      this.counter = 5;
    }


      this._langToggle.getLanguage().subscribe(
        lang => {
          this.lang = lang.toString();
        });

  }


  checkedState(event, checkBox){
     if(event.target.checked === true){
        if(this.counter < this.checkedLimit){
            this.counter++;
        } else {
            event.target.checked = false;
        }
      } else if(this.counter > 0){
          let index = event.target.name;
          console.log('index is ', index);
          console.log('Answer Control Array is ', this.answerControlArr);
          console.log('Answer control is ', this.answerControlArr[index])
          this.counter--;
      }
  }

  onSubmit(pvqForm: any) {
    console.log('4176-21 Submitted data --> {}', pvqForm);
    console.log(pvqForm._value);
    Object.keys(pvqForm._value).map((key) => {
      console.log('4176-21 Object Key: ', key, ' Object Value: ', pvqForm._value[key]);
    })
  }

}

完整 HTML:

 <div class="container">
  <div class="row">
    <div class="col-md-12">
      <div class="container-generic bg-rbc-white">

      <div class="row">
        <div class="container-generic col-md-12">
          <h1>Some Message about PVQS</h1>
          <p>Maecenas sed diam eget risus varius blandit sit amet non magna. Maecenas faucibus mollis interdum.</p>
        </div>
      </div>

      <form [formGroup]="pvqForm" (ngSubmit)="onSubmit(pvqForm)" novalidate>
        <div *ngFor="let question of questions; let i = index" class="row container-generic">
          <div class="col-md-8">
            <div class="container-input-checkbox">
              <label class="container-flex">
                <input #checkBox class="pvq-create-checkbox" type="checkbox" name="{{i}}" (change)="checkedState($event, checkBox)" [checked]="question.answer"> 
                <div class="pvq-create-label">
                  <div *ngIf="lang == 'en'">
                      <p>{{ question.question_EN }}</p>
                  </div>
                  <div *ngIf="lang == 'fr'">
                      <p>{{ question.question_FR }}</p>
                  </div>
                </div>
              </label>
              <label [@hideShow]="checkBox.checked ? 'show' : 'hide'" >Answer
                <input minlength=4 formControlName='answerControl{{i}}' type="textbox" name="{{i}}" value="{{ question.answer }}">
                <div *ngIf="!{{i}}.valid" class="inline-validation critical">
                  <p>Error</p>
                </div>
              </label>
            </div>
          </div>
        </div>

      <div class="row">
        <div class="col-md-12">
          <button [disabled]="pvqForm.invalid" class="button-primary" aria-label="Continue" type="submit">Continue</button>
          <button *ngIf="deadlinePassed" class="button-secondary">Postpone</button>
        </div>
      </div>
     </form>

      </div>
    </div>
  </div>
</div>

您可以使用 minlength 指令添加 minlength 验证器:

<input minlength=4 formControlName='answerControl{{i}}' type="textbox" name="" value="{{ question.answer }}">

您还需要在验证中使用以下语法来定位特定控件div:

<div *ngIf="!pvqForm.controls['answerControl' + i].valid">Error here</div>

Here is the plunker 显示解决方案和相关代码:

TS

export class AppComponent {
  questions = [
    new FormControl('0'),
    new FormControl('1'),
    new FormControl('2')
  ];

  pvqForm = new FormGroup({
    answerControl0: this.questions[0],
    answerControl1: this.questions[1],
    answerControl2: this.questions[2],
  });

HTML

<form [formGroup]="pvqForm" novalidate>
    <div *ngFor="let question of questions; let i = index">
        <input minlength=4 formControlName='answerControl{{i}}' type="text" name="{{i}}">
        <div *ngIf="!pvqForm.controls['answerControl' + i].valid" class="inline-validation critical">
            <p>Error</p>
        </div>
    </div>
</form>

您可能还想添加对 touched 状态的检查

pvqForm.controls['answerControl' + i].touched

因此只有在与控件进行交互时才会显示错误:

<div *ngIf="!pvqForm.controls['answerControl' + i].valid && pvqForm.controls['answerControl' + i].touched" ...>

您也可以在组件中手动设置验证器class:

pvqForm.answerControl0.setValidators(Validators.minLength(4))

您的模板应如下所示

<input minlength="4" formControlName='answerControl{{i}}' type="textbox" name="" value="{{ question.answer }}">

并在您的 .ts 文件中

this.answer_0 = new FormControl(this.questionsArr[0][2], Validators.required);

也尝试将 novalidate 添加到表单元素 <form.... novalidate>