无法验证Angular 6 this.fb.array

时间:2019-06-20 03:52:08

标签: angular typescript

我想对我的复选框FormBuilder.array进行验证,但是尽管选中了其中一​​个复选框,但该表单仍然无效。

我已经尝试过Validators.requiredValidators.requiredTrue,但仍然无法按预期运行

TS:

this.Form = this.fb.group({
  stage: this.fb.array([], Validators.required)
})

HTML:

<div class="form-check-label">
  <label class="checkbox-inline">
    <input type="checkbox" class="checkbox" name="none" value="1" #noneChk
      (change)="onCheckArray($event, Form.value.stage)">
    Stage 1
  </label>
</div>
<div class="form-check-label">
  <label class="checkbox-inline">
    <input type="checkbox" class="checkbox" name="self" value="2" #selfChk
      (change)="onCheckArray($event, Form.value.stage)">
    Stage 2
  </label>
</div>

<p>{{ this.Form.valid | json }}</p>

我有我的StackBlitz here

2 个答案:

答案 0 :(得分:1)

关于您的堆叠闪电战,我forked your stackblitz

问题在于您的函数onCheckArray不会更改FormArray(是的,您更改了值,但未更改FormArray,因此进行了任何验证。请参见编辑的函数

//I repite the getter stage, so the answer can be understood

get stage(): FormArray {
  return this.Form.get('stage') as FormArray;
}

onCheckArray(event) { //you needn't send the value
    /* Selected */
    if (event.target.checked) {
      // Add a new control in the arrayForm, 
      // use push, but add a new FormControl TO the formArray
      this.stage.push(new FormControl(event.target.value));
    } else {
      /* unselected */
      // find the unselected element
      let i: number = 0;

       //we iterate over the formArray
      for (i = 0; i < this.stage.value.length; i++) {
        if (this.stage.value[i] == event.target.value) {
          //use removeAt(i)
          this.stage.removeAt(i);
          return;
        }
      }
    }
  }

好吧,您的函数验证器可以更简单,只需检查数组的长度即可

minSelectedCheckboxes(min = 1) {
    return (formArray: FormArray) => {
      return formArray.controls.length >= min ? null : { required: true };
    };

}

如果初始化FormArray会出现问题

this.Form = this.fb.group({
  stage: this.fb.array([new FormControl("3")], this.minSelectedCheckboxes())
})

您的.html必须像

 <div class="form-check-label">
    <label class="checkbox-inline">
      <input type="checkbox" class="checkbox" name="none" value="1" #noneChk 
          <!--see how indicate when is checked-->
          [checked]="stage.value.indexOf('1')>=0"
           (change)="onCheckArray($event)">
      1
    </label>
  </div>

嗯,我想问的是一种管理数组复选框的更简单方法,我们可以采取另一种方式。我们的FormArray将是一个值为true / false的控件数组,并且我们可以通过函数htht将该数组转换为我们的值。

  options=["1","2","3","4"]; //our options
  get valuesSelected() ; //a function that return the options selected
  {
      return this.options.filter((x,index)=>this.newForm.get('stage').value[index])
  }
  //see how create the formArray, always has the same number of 
  //elements that our options

  this.newForm=new FormGroup({
        stage:new FormArray(this.options
             .map(x=>new FormControl(false)),this.minTrueCheckboxes())
  })

  minTrueCheckboxes(min = 1) {
    return (formArray: FormArray) => {
      return formArray.value.filter(x=>x).length>=min? null : { required: true };
    };
  }

我们的.html变得像

<form class="form" [formGroup]="newForm" (ngSubmit)="onSubmit()">
  <div formArrayName="stage">
    <label class="checkbox-inline" *ngFor="let control of newForm.get('stage').controls;let i=index">
      <input type="checkbox" class="checkbox" [formControl]="control" >
          {{options[i]}}
    </label>
  </div>
</form>

<p>{{ valuesSelected | json }}</p>

答案 1 :(得分:0)

可以在自己的组件中创建自定义验证器 或外面。

您可以在this stackblitz

中看到两个模型
//In the own component
this.form = new FormGroup({
      checks: new FormArray([
        new FormControl(true),
        new FormControl(false),
      ], this.AtLeatOne()), //sii that call it as this.AtLeastOne
    });

AtLeatOne() {
    return (control: FormArray) => {
      if (control.value.find(x => x))
        return null
      return { "error": "You must select at least one option" }
    }
  }

//OutSide
    this.form2 = new FormGroup({
      checks: new FormArray([
        new FormControl(true),
        new FormControl(false),
      ], AtLeatOneValidator())
    });

export function AtLeatOneValidator()
{
  return (control: FormArray)=> {
      if (control.value.find(x => x))
        return null
      return { "error": "You must select at least one option" }
  }
}

好吧,如果要向函数发送参数(我想我们希望用户至少选择2个选项),我给出了最一般的例子。