未通过ngFor生成的值

时间:2017-07-23 18:55:01

标签: angular angular-reactive-forms reactive-forms

我尝试过使用空白项目,但它确实有效。然而,在我正在进行的当前项目中,我在输入字段上有一堆生成动态表单控件的问题。我有minlength = 4的验证集。问题是,当NgFor使用值呈现表单时 - 如果值不符合要求,则内联验证不会触发,直到我更改内容为止输入字段。

另外,我注意到当我提交表单时,如果我不更改值,它们会显示为null。但是当我进行更改时,它们会显示为已更改。被困在这个组件上几天了......我解决了一件事,另一件事打破了。

 <form [formGroup]="pvqForm" (ngSubmit)="onSubmit(pvqForm)" novalidate>
      <div *ngFor="let question of questions | sortBy: 'selected'; let i = index" class="row container-generic">
          <div class="col-md-8">
            <div class="container-input-checkbox">
              <label class="container-flex">
              <input formControlName='questionControl{{ question.question_id }}' #checkBox class="pvq-create-checkbox" type="checkbox" [name]="question.question_id" (change)="checkedState($event, checkBox)" [checked]="isChecked(question)"> 
              <div class="pvq-create-label">
                <div *ngIf="lang == 'en'">
                    <p aria-label="English Question">{{ question.EN }}</p>
                </div>
                <div *ngIf="lang == 'fr'">
                    <p aria-label="French Question">{{ question.FR }}</p>
                </div>
              </div>
            </label>
              <label [@hideShow]="checkBox.checked ? 'show' : 'hide'">Answer
              <input minlength=4 formControlName='answerControl{{ question.question_id }}' type="textbox" name="{{ question.question_id }}" [value]="question.answer ? question.answer : ''">
              <div *ngIf="!pvqForm.controls['answerControl' + question.question_id ].valid" style="color: red;">
                {{ "MINLENGTH" | translate }}
              </div>
            </label>
            </div>
        </div>
      </div>


    this.pvqForm = new FormGroup({
  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,
  answerControl20: this.answer_20,
  questionControl1: this.question_1,
  questionControl2: this.question_2,
  questionControl3: this.question_3,
  questionControl4: this.question_4,
  questionControl5: this.question_5,
  questionControl6: this.question_6,
  questionControl7: this.question_7,
  questionControl8: this.question_8,
  questionControl9: this.question_9,
  questionControl10: this.question_10,
  questionControl11: this.question_11,
  questionControl12: this.question_12,
  questionControl13: this.question_13,
  questionControl14: this.question_14,
  questionControl15: this.question_15,
  questionControl16: this.question_16,
  questionControl17: this.question_17,
  questionControl18: this.question_18,
  questionControl19: this.question_19,
  questionControl20: this.question_20
});

  checkedState(event, checkBox) {
let question_id = checkBox.name;
if (event.target.checked === true) {
  if (this.counter < this.checkedLimit) {
    //Sets validator for newly checked questions
    // this.setValidator(question_id);
    //Add the validator for the checkbox checked
    this.counter++;
  } else {
    event.target.checked = false;
    this.answerControlArr[question_id - 1].setValue(null);
    // this.removeValidator(question_id);
  }
} else if (this.counter > 0) {
  //When clicking off the checkbox, set value to null
  this.answerControlArr[question_id - 1].setValue(null);
  // this.removeValidator(question_id);
  this.counter--;
}
}

我尝试过设置验证器并根据检查状态动态删除它们,但没有运气。这导致表单无效。

setValidator(questionId) {
//Set Min length Validator
this.answerControlArr[questionId - 1].setValidators(Validators.minLength(4));
//Set the value
// if(this.questionsArr[questionId - 1][3]){
//   this.answerControlArr[questionId - 1].setValue(this.questionsArr[questionId - 1][3]);
// }
//Check if Value is "" or does not meet the validator requirement
// if(this.answerControlArr[questionId - 1].value == null){
//     this.answerControlArr[questionId - 1].setErrors({"minLength": true});
// }
if (this.answerControlArr[questionId - 1].value == null || this.answerControlArr[questionId - 1].value.length < 5) {
  this.answerControlArr[questionId - 1].setErrors({ "minLength": true });
}
}

  removeValidator(questionId){
this.answerControlArr[questionId - 1].clearValidators();

} enter image description here

1 个答案:

答案 0 :(得分:0)

<强>注意: 使用更简单的方法可以实现相同的功能。例如,可以通过按钮选择问题并将其推送到表单,而不是从开始就将所有问题都放在我们的表单中。

但我选择这种方法来满足问题的确切要求。

当我第一次开始角度时,我遇到了与表格类似的问题。但角度和反应形式的力量和简单性帮助我度过了难关。 现在你主要在模板上做你的表格。相反,您可以在模型中完全控制它。

组件

在您的组件中:

 export class QuestionsComponent {

      // Our empty Form
      myForm: FormGroup;
      questions = [
         {question: 'Question 1'},
         {question: 'Question 2'},
         {question: 'Question 3'},
         {question: 'Question 4'},
         {question: 'Question 5'},
         {question: 'Question 6'}
      ];

      constructor(private fb: FormBuilder) {
          // We inject FormBuilder to our component

          // Now, we instantiate myForm with FormBuilder
          // Notice that myForm is a FormGroup which contains an empty FormArray
           this.myForm = this.fb.group({
                    questions: this.fb.array([])
                }, {validator: this.questionsValidator}
           );

           for (let i = 0; i < this.questions.length; i++) {
               this.addRow(this.questions[i]);
           }
      }
  }

创建一个新问题:

initItems(question): FormGroup {
    // Here, we make the form for each question

    return this.fb.group({
        checked: [false],
        question: [question.question],
        answer: [null]
    });
}

 addRow(question) {

    // We get our FormArray
    const control = <FormArray>this.myForm.controls['questions'];

    // instantiate a new question FormGroup;
    let newQuestionGroup = this.initItems(question);

    // Add it to our formArray
    control.push(newQuestionGroup);
}

最后我们使用自定义验证器验证我们的表单:

questionsValidator(control: AbstractControl): { [key: string]: boolean } {

        const formData = <FormArray>control.get('questions');
        let answeredCount = 0;
        for (let i = 0; i < formData.value.length; i++) {
            let singleQuestion = formData.controls[i];
            if (singleQuestion.value.checked && singleQuestion.value.answer !== null && singleQuestion.value.answer.length > 4) {
                answeredCount += 1;
            }
        }

        return answeredCount >= 5 ? null : {valid: true};
    }

模板

    <pre>{{myForm.value | json}}</pre>

    <h3>Form is valid: {{myForm.valid}}</h3>

    <form [formGroup]="myForm">
        <table formArrayName="questions">
            <tr *ngFor="let item of myForm.controls.questions.controls; let i=index" [formGroupName]="i">

                <td>
                    <input type="checkbox" formControlName="checked" value="bike">
                </td>
                <td>{{myForm.controls.questions.controls[i].value.question}}</td>
                <td>
                    <input type="text" min='0' formControlName="answer">
                </td>
            </tr>
        </table>
    </form>