Angular FormArray复选框

时间:2019-06-16 14:14:24

标签: angular forms typescript formarray

什么是设置此代码的正确方法。我想用户选择复选框,然后将其复选框值推入FormArray,现在我得到[true,false,false]输出

data = ['Marka', 'Kilometraza', 'Alu felne'];

addCheckboxes() {
    this.data.map((o, i) => {
      const control = new FormControl(i === 0);
      this.checkboxes.controls.push(control);
    });
  }

HTML

<div formArrayName="checkboxes" *ngFor="let check of regForm.get('detaljne').get('checkboxes').controls;index as i">
   <mat-checkbox [formControlName]="i">{{ data[i] }}</mat-checkbox>
</div>

现在,当第一个复选框选中时,我得到[true,false,false]输出,但是我想获取所选复选框的值,因此只有所选复选框的值位于该FormArray中,所以当带有标签'Marka的复选框时比FormArray的'被检查为['Marka']

2 个答案:

答案 0 :(得分:1)

另一种方法是使用自定义表单控件。看看stackblitz

自定义控件接受两种类型的“数据”,像这样的简单数组

data = ['Marka', 'Kilometraza', 'Alu felne'];

或对象数组。您看到的第一个字段是“键”,第二个字段是您的“文本”

dataValue=[{value:1,text:'Marka'}, 
           {value:2,text:'Kilometraza'},
           {value:3,text:'Alu felne'}]

代码,我将尝试解释n条注释,例如:

@Component({
  selector: 'check-box-list',
  template: `
  <div [formGroup]="formArray">
    <!--see the "special way" we refereed to the elements of formArray
         using [fromControl]="variable of loop"
    -->
    <div *ngFor="let check of formArray.controls;let i=index">
           <!--we show or _data[i] or _data[i][text], see below -->
      <mat-checkbox [formControl]="check">{{key?_data[i][text]:_data[i]}}</mat-checkbox>
    </div>
  `,
   <!--it's necesary a provider NG_VALUE_ACCESSOR-->
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CheckBoxListComponent),
      multi: true
    }
  ]
})
export class CheckBoxListComponent implements ControlValueAccessor {
  formArray: FormArray = new FormArray([])
  isValue: boolean = false;
  text: string;  //I stored in "text" the field that it's showed
  key: string;   //I stored in "key" the field that has the "value"
  _data

  @Input() set data(value) {
    this._data = value;
    //data[0] can be an array or a string/number
    //if is an object we get the "keys", e.g.
    //data[0]={value:....,text:....}, this.getOrderedKeys return an array ["value","text"]
    const keys = typeof (value[0]) == 'object' ? this.getOrderedKeys(value[0]) : null
    if (keys) {
      this.key = keys[0]
      this.text = keys[1]
    }
  }

  onChange;
  onTouched;

  writeValue(value: any[] | any): void {
    //with each value of "data" we create a formControl with value true or false
    this.formArray = new FormArray(
      this._data.map((x, index) =>
        new FormControl(value.indexOf(this.key ? this._data[index][this.key] :
                                      this._data[index]) >= 0)))

    //we subscribe to the formArray valueChanges
    this.formArray.valueChanges.subscribe((res) => {
      this.onTouched()  //we mark as touched the custom form control
      //we make a filter of data
      const response = res.indexOf(true) >= 0 ?
        this._data.filter((x, index) => this.formArray.value[index]) :
        null
      //if has key, return only the array with the keys
      this.onChange(response == null ? null : this.key ? 
                 response.map(x => x[this.key]) : 
                 response)

    })
  }


  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    //if we disabled/enabled the control simply disabled/enabled the controls
    this.formArray.controls.forEach(c => {
      if (isDisabled)
        c.disable();
      else
        c.enable();
    })
  }

  getOrderedKeys(obj): string[] {
    return JSON.stringify(obj)
      .replace(/[&\/\\#+()$~%.'"*?<>{}]/g, '')
      .split(',')
      .map(x => x.split(':')[0]);
  }
}

我们可以使用like

<form [formGroup]="form3">
  <check-box-list [data]="dataValue" formControlName="checkboxes">
  </check-box-list>
 </form>
//where
   this.form3=new FormGroup(
      {
        checkboxes:new FormControl([1,3])
      }
    )

答案 1 :(得分:0)

您可以将从formArray接收到的值与data合并:

newCheckboxValue.map((value, index) => value ? data[index] : null).filter(value => value)

将布尔数组转换为标签/空数组,然后删除空