I'm trying to re-use my create-form
to edit the values of the form. My checkbox is working as per requirement while creating a form. When I click on edit form, the values aren't patching to my checkbox. Below is my code which I have tried:
<div class="form-row">
<div class="form-group col-sm-6">
<label>Authorized To</label>
<br>
<label *ngFor="let choice of authorized; let i=index">
<input type="checkbox" [value]="choice" (change)="onCheckChange($event)" [checked]="checkedVal"
formArrayName="authorized" type="checkbox[class.invalid]="! formGrowLicense.controls['authorized'].valid && formGrowLicense.controls['authorized'].touched ">
{{choice}}
</label>
<div *ngIf="!formGrowLicense.controls['authorized'].valid && (formGrowLicense.controls['authorized'].touched || isSubmitted)">
<div class="invalid-feedback" style="display: block;">Please enter authorized to</div>
</div>
</div>
</div>
ts
authorized: any = ['CULTIVATE', 'HARVEST', 'PROCESS']; //displaying list of checkbox
constructor() {
this.formGrowLicense = this.formBuilder.group({
businessName: ['', Validators.required],
authorized: new FormArray([], [Validators.required])
});
}
getGrowLicense(id) {
this.httpService.getGrowLicenseById(id).subscribe(
response => {
this.patchGrowLicense(response);
this.checkedVal = response.authorisedTo; // tried storing response in this variable ['CULTIVATE','HARVEST']
},
(err: any) => console.log(err)
);
}
patch(licenseObj){
this.formGrowLicense.patchValue({
businessName:licenseObj.companyName,
authorized: licenseObj.authorisedTo, // here i'm getting response ['CULTIVATE','HARVEST']. Need to patch these two values as checked in checkbox
});
}
onCheckChange(event) {
this.formArray = this.formGrowLicense.get(
'authorized'
) as FormArray;
/* Selected */
if (event.target.checked) {
console.log(event.target.value);
// Add a new control in the arrayForm
this.formArray.push(new FormControl(event.target.value));
} else {
/* unselected */
// find the unselected element
let i = 0;
this.formArray.controls.forEach((ctrl: FormControl) => {
if (ctrl.value == event.target.value) {
// Remove the unselected element from the arrayForm
this.formArray.removeAt(i);
return;
}
i++;
});
}
}
You has an FormArray of FormControls that takes values true/false and received and array of strings among a fixed array, so first you need transform the array received in an array of true/false
First approach
First we are going to create a Form with a formArray. As always we can manage a form array we need to create a getter that return our formArray
//our getter formArray
get authorizedArray()
{
return this.formGrowLicense.get('authorized') as FormArray
}
ngOnInit()
{ //we create the formArray
this.formGrowLicense=new FormGroup({
businessName:new FormControl(),
authorized:new FormArray(this.authorized.map(x=>new FormControl(false)))
})
}
See that the way to create the formArray is using new FormArray(..here and array of formControls..)
. And the way to create the formArray of formControls is "mapping" each element of the array "this.autorized" to a FormControl.
To manage in a series of inputs we using this.html
<form [formGroup]="formGrowLicense">
<input formControlName="businessName">
<!--we use formArrayName in a div-->
<div formArrayName="authorized">
<!--we iterate over autorizedArray.controls
remember our getter of the formArray? -->
<div *ngFor="let control of authorizedArray.controls;let i=index">
<!--we use [formControlName]=i -->
<label><input type="checkbox" [formControlName]="i">{{authorized[i]}}</label>
</div>
</div>
</form>
As always, we check if it's all ok using (only for check) in the.html
<pre>
{{formGrowLicense?.value|json}}
</pre>
See how we iterate over the formArrayControls, and use the index, to show in the label authorized[i]
Well, We know yet how control a form array, so the next question: how we feed the formArray with the values?
Remember that we received some like, eg
{
businessName:'my business name'
authorized:['CULTIVATE', 'PROCESS']
}
when we received the value in data we can use some like
this.formGroupLicense.patchValue(
{
businessName:data.businessName,
authorized:this.authorized.map(x=>data.authorized.indexOf(x)>=0)
}
See how transform the "data.authorize" and array with 0,1,2 or 3 elements in an array of 3 elements that takes values true or false
Well, the last work we need is, in submit, use the values of the formArray (eg [true,false,false] to get an array of strings
submit(form)
{
if (form.valid)
{
const data={
businessName:form.value.businessName
authorize:form.value.authorized.map(
(x,index)=>x?this.authorized[index]:null)
.filter(x=>x)
}
console.log(data) //<--here we has the data we send to the service
}
}
Yes, we map the [true,false,false]
to ['CULTIVATE',null,null]
and filter and only want elements that are not null ['CULTIVATE']
Well, use pathValue is ok but why we not create a function that return a formGroup with the data we want
createFormGroup(data:any=null)
{
data=data||{businessName:null,authorize:[]}
return new FormGroup({
businessName:new FormControl(data.businessName),
authorized:new FormArray(this.authorized
.map(x=>new FormControl(data.authorized.indexOf(x)>=0)))
})
}
So, when we received the data the only thing we need is use
this.formGroupLicense=this.createFormGroup(data)
Second approach
We has a form like
this.formGrowLicense=new FormGroup({
businessName:new FormControl(),
authorized:new FormControl()
})
YES. authorized is a FormControl that store an array. If you see the material multi checked is this approach. For this you can check this SO with use a custom formControl. Let me explain (I don't want a customFormControl)
We has an auxiliary array with two properties "name" and "value" we want to get some like eg
authorizedAux: any = [{name:'CULTIVATE',value:true},
{name:'HARVEST',value:false},
{name:'PROCESS',value:true}]
So we add a function
setAutorized(data: string[]) {
this.authorizedAux = this.authorized.map(x => ({
name: x,
value: data.indexOf(x) >= 0
}));
}
And another function parse
parse() {
const result=this.authorized
.map((x, index) => (this.authorizedAux[index].value ? x : null))
.filter(x => x);
return result.length>0?result:null
}
then we can has an html that use ngModel, ngModelChange and ngModelOptions to change the value of the FormControl
<form [formGroup]="form">
<input formControlName="businessName">
<div *ngFor="let control of authorizedAux">
<label>
<input type="checkbox"
[ngModel]="control.value"
(ngModelChange)="control.value=$event;form.get('authorized').setValue(parse())"
[ngModelOptions]="{standalone:true}"
>{{control.name}}</label>
</div>
</form>
Remember that, when received the data we need call to the function setAutorized
See the two approaches in the stackblitz
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.