Angular formarray checkboxes

前端 未结 2 380
栀梦
栀梦 2020-12-22 03:24

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,fal

相关标签:
2条回答
  • 2020-12-22 03:47

    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])
          }
        )
    
    0 讨论(0)
  • 2020-12-22 03:54

    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

    0 讨论(0)
提交回复
热议问题