133

So I have a complex form for creating an entity and I want to use it for editing as well I am using new angular forms API. I structured the form exactly as the data I retrieve from the database so I want to set the value of the whole form to the data retrieved here is an example to what i want to do:

this.form = builder.group({
      b : [ "", Validators.required ],
      c : [ "", Validators.required ],
      d : [ "" ],
      e : [ [] ],
      f : [ "" ]
    });
this.form.value({b:"data",c:"data",d:"data",e:["data1","data2"],f:data});

PS: NgModel doesn't work with new forms api also i don't mind using one way data binding in template as in

<input formControlName="d" value="[data.d]" />

that works but it would be a pain in case of the arrays

3
  • As far as I know setting a forms value is currently not supported and will be supported after the next update (RC.5). Please provide a Plunker. Commented Jul 29, 2016 at 9:57
  • @GünterZöchbauer check my current solution Commented Jul 29, 2016 at 13:55
  • Di you look at: github.com/angular/angular/blob/2.0.0-rc.5/modules/%40angular/… line 553 FormGroup.setValue() ? Commented Aug 11, 2016 at 15:16

8 Answers 8

407

To set all FormGroup values use, setValue:

this.myFormGroup.setValue({
  formControlName1: myValue1, 
  formControlName2: myValue2
});

To set only some values, use patchValue:

this.myFormGroup.patchValue({
  formControlName1: myValue1, 
  // formControlName2: myValue2 (can be omitted)
});

With this second technique, not all values need to be supplied and fields whos values were not set will not be affected.

Sign up to request clarification or add additional context in comments.

2 Comments

I'm using patchValue in a nested form and it is overwriting all the fields in the form. (even those I don't specify) any idea what I'm doing wrong?
@Enrico, without ur code I can not help u.
22

You can use form.get to get the specific control object and use setValue

this.form.get(<formControlName>).setValue(<newValue>);

2 Comments

How to pass array to new value
@RaviShah it is JSON syntax
12

For set value when your control is FormGroup can use this example

this.clientForm.controls['location'].setValue({
      latitude: position.coords.latitude,
      longitude: position.coords.longitude
    });

Comments

6

Yes you can use setValue to set value for edit/update purpose.

this.personalform.setValue({
      name: items.name,
      address: {
        city: items.address.city,
        country: items.address.country
      }
    });

You can refer https://musttoknow.com/use-angular-reactive-form-addinsert-update-data-using-setvalue-setpatch/ to understand how to use Reactive forms for add/edit feature by using setValue. It saved my time

Comments

4

As pointed out in comments, this feature wasn't supported at the time this question was asked. This issue has been resolved in angular 2 rc5

Comments

3

I have implemented a temporary solution until angular2 support form updateValue

 initFormGroup(form: FormGroup, data: any) {
        for(var key in form.controls) {
          console.log(key);
          if(form.controls[key] instanceof FormControl) {
            if(data[key]){
              let control = <FormControl>form.controls[key];
              this.initFormControl(control,data[key]);
            }
          } else if(form.controls[key] instanceof FormGroup) {
            if(data[key]){
              this.initFormGroup(<FormGroup>form.controls[key],data[key]);
            }
          } else if(form.controls[key] instanceof FormArray) {
            var control = <FormArray>form.controls[key];
            if(data[key])
            this.initFormArray(control, data[key]);
          }
        }
      }
      initFormArray(array: FormArray, data: Array<any>){
    if(data.length>0){
      var clone = array.controls[0];
      array.removeAt(0);
      for(var idx in data) {
        array.push(_.cloneDeep(clone));
        if(clone instanceof FormGroup)
          this.initFormGroup(<FormGroup>array.controls[idx], data[idx]);
        else if(clone instanceof FormControl)
          this.initFormControl(<FormControl>array.controls[idx], data[idx]);
        else if(clone instanceof FormArray)
          this.initFormArray(<FormArray>array.controls[idx], data[idx]);
      }
    }
  }


initFormControl(control: FormControl, value:any){
    control.updateValue(value);
  }

usage:

this.initFormGroup(this.form, {b:"data",c:"data",d:"data",e:["data1","data2"],f:data});

note: form and data must have the same structure and i have used lodash for deepcloning jQuery and other libs can do as well

Comments

0

"NgModel doesn't work with new forms api".

That's not true. You just need to use it correctly. If you are using the reactive forms, the NgModel should be used in concert with the reactive directive. See the example in the source.

/*
 * @Component({
 *      selector: "login-comp",
 *      directives: [REACTIVE_FORM_DIRECTIVES],
 *      template: `
 *        <form [formGroup]="myForm" (submit)='onLogIn()'>
 *          Login <input type='text' formControlName='login' [(ngModel)]="credentials.login">
 *          Password <input type='password' formControlName='password'
 *                          [(ngModel)]="credentials.password">
 *          <button type='submit'>Log in!</button>
 *        </form>
 *      `})
 * class LoginComp {
 *  credentials: {login:string, password:string};
 *  myForm = new FormGroup({
 *    login: new Control(this.credentials.login),
 *    password: new Control(this.credentials.password)
 *  });
 *
 *  onLogIn(): void {
 *    // this.credentials.login === "some login"
 *    // this.credentials.password === "some password"
 *  }
 * }
 */

Though it looks like from the TODO comments, this will likely be removed and replaced with a reactive API.

// TODO(kara):  Replace ngModel with reactive API
@Input('ngModel') model: any;

5 Comments

coming from angular2 api docs NgModel selector [ngModel]:not([formControlName]):not([formControl]) angular.io/docs/ts/latest/api/forms/index/… so even if it works now it will be removed later i think i will implement a manual value injector as it will be a more stable solution
@AmgadSerry that is to make sure that it doesn't interfere with those components (in the selector). The FormControlName explicitly adds it as an @Input(). See the source I linked to. If those negating selectors weren't there, then with the example above, an NgModel would be created, which you don't want.
It's a little confusing, but that's just how it's implemented. For both FormControlDirective ([formControl]) and FormControlName (formControlName), this is how it works. If the ngModel is used without one of those, then it is assumed you will be using declarative forms, and an NgModel is created. If the ngModel is used alongside one of the reactive form directives, then that reactive form directive will handle the model, not an NgModel
oh i thought they made that as a hack to enable ngModel on those two directives only for the time being and they will remove it later
check my current solution
0

Declarando o formGroup :

formGroup = new FormGroup({
    value01: new FormControl('', Validators.required),
    value02: new FormControl('', Validators.required),
    value03: new FormControl('', Validators.required)
  });

Para alterar TODOS os valores é utilizado setValue :

this.formGroup.setValue({
    value01: this.value01,
    value02: this.value02,
    value03: this.value03
  });

Para alterar sómente UM ou MAIS valores é utilizado patchValue :

this.formGroup.patchValue({
    value01: this.value01,
    value02: this.value02
  });

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.