Angular formarray checkboxes

房东的猫 提交于 2019-12-24 19:09:41

问题


what is the proper way to setup this code. I want to user select checkbox and value of that checkbox to be pushed into FormArray now I get [true,false,false] output

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>

Now I get [true,false,false] output when first checkbox is checked but I want to get value of selected checkboxes, so only values of selected checkboxes to be in that FormArray, So when checkbox with label 'Marka' is checked than FormArray to be ['Marka']


回答1:


Another way is used a custom form control. Take a look the stackblitz

The custom control admit two type of "data", a simple array like

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

Or a array of object. the first field becomes the "key" and the second one the "text" you see

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

The code, I'll try explain n comments is like:

@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]);
  }
}

We can use 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])
      }
    )



回答2:


You can merge value received from formArray with data:

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

Transforming bool array to array of labels/null, then removing null



来源:https://stackoverflow.com/questions/56619632/angular-formarray-checkboxes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!