Angular2 establece el valor para formGroup

91

Así que tengo una forma compleja para crear una entidad y también quiero usarla para editar. Estoy usando una nueva API de formas angulares. Estructuré el formulario exactamente como los datos que recupero de la base de datos, por lo que quiero establecer el valor de todo el formulario en los datos recuperados. Aquí hay un ejemplo de lo que quiero hacer:

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});

PD: NgModel no funciona con la nueva API de formularios y no me importa usar el enlace de datos unidireccional en la plantilla como

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

Eso funciona, pero sería una molestia en el caso de las matrices

Amgad Serry
fuente
Hasta donde yo sé, la configuración de un valor de formularios no se admite actualmente y será compatible después de la próxima actualización (RC.5). Proporcione un Plunker.
Günter Zöchbauer
@ GünterZöchbauer compruebe mi solución actual
Amgad Serry
¿ Miraste en: github.com/angular/angular/blob/2.0.0-rc.5/modules/%40angular/… línea 553 FormGroup.setValue ()?
Clemente

Respuestas:

298

Para establecer todos los valores de FormGroup, use setValue :

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

Para establecer solo algunos valores, use patchValue :

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

Con esta segunda técnica, no es necesario proporcionar todos los valores y los campos cuyos valores no se establecieron no se verán afectados.

Stephen Paul
fuente
1
Estoy usando patchValue en un formulario anidado y está sobrescribiendo todos los campos del formulario. (incluso aquellos que no especifico) alguna idea de lo que estoy haciendo mal?
Enrico
9

Para establecer un valor cuando su control es FormGroup, puede usar este ejemplo

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

Puede usar form.get para obtener el objeto de control específico y usar setValue

this.form.get(<formControlName>).setValue(<newValue>);
Trabajo de Varadhan
fuente
3

Como se señaló en los comentarios, esta función no era compatible en el momento en que se hizo esta pregunta. Este problema se ha resuelto en angular 2 rc5

Amgad Serry
fuente
2

He implementado una solución temporal hasta el formulario de soporte angular2 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);
  }

uso:

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

nota: el formulario y los datos deben tener la misma estructura y he usado lodash para deepcloning jQuery y otras bibliotecas también pueden hacerlo

Amgad Serry
fuente
0

"NgModel no funciona con la nueva API de formularios".

Eso no es cierto. Solo necesitas usarlo correctamente. Si está utilizando las formas reactivas, el NgModel debe utilizarse junto con la directiva reactiva. Vea el ejemplo en la fuente .

/*
 * @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"
 *  }
 * }
 */

Aunque parece de los comentarios TODO , es probable que se elimine y se reemplace con una API reactiva.

// TODO(kara):  Replace ngModel with reactive API
@Input('ngModel') model: any;
Paul Samsotha
fuente
proveniente de angular2 api docs NgModel selector [ngModel]: not ([formControlName]): not ([formControl]) angular.io/docs/ts/latest/api/forms/index/… así que incluso si funciona ahora lo será eliminado más tarde, creo que implementaré un inyector de valor manual, ya que será una solución más estable
Amgad Serry
@AmgadSerry que es para asegurarse de que no interfiera con esos componentes (en el selector). El FormControlNamelo agrega explícitamente como un @Input(). Ver la fuente a la que me vinculé. Si esos selectores de negación no estuvieran allí, entonces con el ejemplo anterior, se crearía un NgModel, que no desea.
Paul Samsotha
Es un poco confuso, pero así es como se implementa. Tanto para FormControlDirective( [formControl]) como para FormControlName( formControlName), así es como funciona. Si ngModelse usa sin uno de esos, se asume que usará formularios declarativos y NgModelse crea un. Si ngModelse usa junto con una de las directivas de forma reactiva , entonces esa directiva de forma reactiva manejará el modelo, no unNgModel
Paul Samsotha
oh, pensé que lo hicieron como un truco para habilitar ngModel en esas dos directivas solo por el momento y lo eliminarán más tarde
Amgad Serry
comprobar mi solución actual
Amgad Serry