Pre-filling input submitted to a `FormGroup` - Angular2
I am using Angular2 - Reactive Forms. Everything works fine as long as I don't want to show the pre-filled value in one of the form fields.
Scenario: There are multiple buttons on the page and each button opens a form with fields like
- Name
- Message
- Product code β The value for this must be pre-filled according to the product code from the service.
Script Failure: Input Product Code value is null.
TS code:
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
queryForm: FormGroup;
constructor(private _productService: ProductService, fb: FormBuilder) {
this.queryForm = fb.group({
'name': [null, Validators.compose([Validators.required, Validators.minLength(5)])],
'email': [
null, [Validators.required, Validators.email]
],
'message': [null,Validators.compose([Validators.required, Validators.minLength(5)])],
'pcode': [
null
],
})
}
HTML form:
<div *ngFor="let item of product">
<form action="#" [formGroup]="queryForm"
(ngSubmit)="submitForm(queryForm.value)" method="post"
novalidate="" class="text-left note" id="f_{{item.productId}}">
[ .... rest of the fields ...]
<div class="form-group hidden">
<input type="hidden " class="form-control " id="pcode " name="pcode"
formControlName="pcode" [value]="item.productCode" />
</div>
<div class="form-group">
<button type="submit" class="btn1" [disabled]="!queryForm.valid">Submit</button>
</div>
</form>
</div>
How can I achieve this?
source to share
UPDATE: As it turned out, you need formArray
one instead formControl
. So declare that when you create the form:
this.queryForm = this.fb.group({ arrayOfData: this.fb.array([]) // name a proper name to array })
You can use setValue
or patchValue
when you got your data where you iterate over the response and correct the values ββin your form array. Call the patchValues
-method in your callback (subscribe).
patchValues() { const control = <FormArray>this.queryForm.controls.arrayOfData; this.items.forEach(x => { control.push(this.patchValue(x.first_name, x.pcode)) }) } patchValue(name, code) { return this.fb.group({ name: [name], pcode: [code] }) }
In your template iterate the formarray and also don't forget to include the formgroupname (which is the index):
<div formArrayName="arrayOfData">
<div *ngFor="let code of queryForm.controls.arrayOfData.controls; let i = index">
<div formGroupName="{{i}}">
<label>Name: </label>
<input formControlName="name" /><br>
<label>Product Code: </label>
<input formControlName="pcode" /><br>
</div>
</div>
</div>
Demo
Original answer:
You should always set the form values ββin the component and not in the template. You can use patchValue
or setValue
when you got the value from the service ... so you can do this, for example, inside a callback (subscribe):
this.myService.getSomeData() .subscribe(data => { this.item = data; this.queryForm.patchValue({pcode: this.item.productCode}) });
Then you don't need to use it [value]="item.productCode"
in your form, this value is set instead of the form control.
Demo
source to share