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


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

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.


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


5

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

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

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


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


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;

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.