Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pre Populate input field in `FormGroup` - Angular2

I am using Angular2 - Reactive Forms. Everything works fine until i want to show a pre-populated value in one of fields in Form.

Scenario: There are multiple buttons on a page and each button opens up a form with fields as

  1. Name
  2. Email
  3. Message
  4. Product Code --> Value for this shall be prepopulated as per item code from service.

Failing Scenario: Product Code input value turns to 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?

like image 948
Gags Avatar asked Apr 17 '17 09:04

Gags


1 Answers

UPDATE: As we found out, you are needing a formArray instead of a single formControl. So declare that when you build form:

this.queryForm = this.fb.group({
  arrayOfData: this.fb.array([]) // name a proper name to array
})

You can use setValue or patchValue when you have received your data, where you iterate the response and patch the values to your form array. Call patchValues-method in your callback (subscribe).

patchValues() {
  const control = <FormArray>this.queryForm.get('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 remember to set the formgroupname (which is the index):

<div formArrayName="arrayOfData">
  <div *ngFor="let code of queryForm.get('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>


Original answer:

You should always set the form values in the component, not the template. You can use patchValue or setValue, when you have received the value from the service... so you can do this e.g inside the callback (subscribe):

this.myService.getSomeData()
  .subscribe(data => {
     this.item = data;
     this.queryForm.patchValue({pcode: this.item.productCode})
  });

Then you do not need to use [value]="item.productCode" in your form, this value is set with the form control instead.

like image 66
AT82 Avatar answered Nov 11 '22 13:11

AT82