问题
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