Establecer manualmente el valor para el control FormBuilder


176

Esto me está volviendo loco, estoy bajo el arma y no puedo permitirme pasar otro día entero en esto.

Estoy tratando de establecer manualmente un valor de control ('departamento') dentro del componente, y simplemente no funciona, incluso el nuevo valor registra para consolarse correctamente.

Aquí está la instancia de FormBuilder:

initForm() {
  this.form = this.fb.group({
    'name': ['', Validators.required],
    'dept': ['', Validators.required],
    'description': ['', Validators.required],
  });
}

Este es el controlador de eventos que recibe el departamento seleccionado:

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // This is how I am trying to set the value
  this.form.controls['dept'].value = selected.id;
}

Ahora, cuando se envía el formulario y cierro la sesión, this.formel campo sigue en blanco He visto otro uso de ppl updateValue()pero este es beta.1 y no lo veo como un método válido para llamar al control.

También intenté llamar updateValueAndValidity()sin éxito :(.

Simplemente lo usaría ngControl="dept"en el elemento de formulario, como lo estoy haciendo con el resto del formulario, pero es una directiva / componente personalizado.

<ng-select
  [data]="dept"
  [multiple]="false"
  [items]="depts"
  (selected)="deptSelected($event)" <!-- This is how the value gets to me -->
  [placeholder]="'No Dept Selected'"></ng-select>

Me había encontrado con una situación similar, el escenario era que el valor se estableció en http.get-subscribe y cargó el valor del formulario, pero al configurar la línea de valor que se ejecuta primero, la suscripción realmente se ejecuta más tarde como asincrónica. así que al establecer el valor en la suscripción, asegúrese de que esté configurado. my2cents!
HydTechie

Respuestas:


326

Actualizado: 19/03/2017

this.form.controls['dept'].setValue(selected.id);

ANTIGUO:

Por ahora nos vemos obligados a hacer un tipo de reparto:

(<Control>this.form.controls['dept']).updateValue(selected.id)

No muy elegante, estoy de acuerdo. Espero que esto se mejore en futuras versiones.


66
Esto funciona bien, gracias. También es necesario borrar la validación: (<Control>this.form.controls['dept']).setErrors(null)
Man Called Haney

17
O todavía this.form.get('dept').setValue(selected.id):)
developer033

66
Solo una nota. También puede acceder a la propiedad directamente sin un indexador. this.form.controls.dept.setValue(selected.id);
James Poulose

¡pero esto no ejecutará la validación para los nuevos datos! ¿Cómo activar manualmente la detección de cambios después de la actualización?
ksh

1
Es 2019 para mí, esto funciona:this.form.controls['dept'].setValue(selected.id);
John Lopez

98

En Angular 2 Final (RC5 +) hay nuevas API para actualizar los valores de los formularios. El patchValue()método API admite actualizaciones parciales de formularios, donde solo necesitamos especificar algunos de los campos:

this.form.patchValue({id: selected.id})

También existe el setValue()método API que necesita un objeto con todos los campos del formulario. Si falta un campo, obtendremos un error.


77
Sólo para añadir que a partir de ahora updateValue(de respuesta aceptada por Filoche) se desaprueba a favor desetValue
superjos

2
Aquí está la solicitud de extracción oficial de Github y la justificación para despreciar updateValue()e introducir patchValuey setValue.
TheBrockEllis

¡pero esto no ejecutará la validación para los nuevos datos! Como la detección de cambios de disparo manualmente después de la actualización
ksh

16

Aangular 2 final ha actualizado las API. Han agregado muchos métodos para esto.

Para actualizar el control de formulario desde el controlador, haga esto:

this.form.controls['dept'].setValue(selected.id);

this.form.controls['dept'].patchValue(selected.id);

No es necesario restablecer los errores.

Referencias

https://angular.io/docs/ts/latest/api/forms/index/FormControl-class.html

https://toddmotto.com/angular-2-form-controls-patch-value-set-value


diferencia entre los dos: setValue()cuando se llama en a formGroup/formBuilder, requiere que se configuren todos los valores del formulario. patchValue(), cuando se llama de la misma manera, podría usarse para actualizar valores específicos.
Vibhor Dube

11

Puede usar los siguientes métodos para actualizar el valor de un control de forma reactiva. Cualquiera de los siguientes métodos se adaptará a sus necesidades.

Métodos que usan setValue ()

this.form.get("dept").setValue(selected.id);
this.form.controls["dept"].setValue(selected.id);

Métodos que usan patchValue ()

this.form.get("dept").patchValue(selected.id);
this.form.controls['dept'].patchValue(selected.id);
this.form.patchValue({"dept": selected.id});

El último método recorrerá todos los controles del formulario, por lo que no es preferible al actualizar un control único

Puede usar cualquiera de los métodos dentro del controlador de eventos

deptSelected(selected: { id: string; text: string }) {
     // any of the above method can be added here
}

Puede actualizar varios controles en el grupo de formularios si es necesario utilizando el

this.form.patchValue({"dept": selected.id, "description":"description value"});

9

Podrías probar esto:

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // This is how I am trying to set the value
  this.form.controls['dept'].updateValue(selected.id);
}

Para obtener más detalles, puede echar un vistazo al JS Doc correspondiente con respecto al segundo parámetro del updateValuemétodo: https://github.com/angular/angular/blob/master/modules/angular2/src/common/forms/model. ts # L269 .


Gracias por su respuesta; sin embargo, updateValue no parece ser un método válido en angular2 beta.1: ¿en qué versión está usted para poder usar ese método?
Matthew Brown

1
Letra de imprenta da el siguiente error: error TS2339: Property 'updateValue' does not exist on type 'AbstractControl'. En ese componente, el formulario tiene el tipo de ControlGroup. Quizás si los creo individualmente con new Control()esto funcionaría
Matthew Brown

5

Ninguno de estos funcionó para mí. Tenía que hacer:

  this.myForm.get('myVal').setValue(val);

Lo mismo pasó conmigo. ¿Por qué es este el caso?
Rehmanali Momin

3
  let cloneObj = Object.assign({}, this.form.getRawValue(), someClass);
  this.form.complexForm.patchValue(cloneObj);

Si no desea configurar manualmente cada campo.


2

Solución actualizada de @ Filoche Angular 2. UtilizandoFormControl

(<Control>this.form.controls['dept']).updateValue(selected.id)

import { FormControl } from '@angular/forms';

(<FormControl>this.form.controls['dept']).setValue(selected.id));

Alternativamente, puede usar la solución de @ AngularUniversity que usapatchValue


1

Sé que la respuesta ya está dada, pero quiero dar una respuesta breve sobre cómo actualizar el valor de un formulario para que otros recién llegados puedan tener una idea clara.

su estructura de formulario es tan perfecta para usarla como ejemplo. entonces, a lo largo de mi respuesta, lo denotaré como la forma.

this.form = this.fb.group({
    'name': ['', Validators.required],
    'dept': ['', Validators.required],
    'description': ['', Validators.required]
  });

por lo que nuestra forma es un FormGroup tipo de objeto que tiene tres FormControl .

Hay dos formas de actualizar el valor del modelo:

  • Use el método setValue () para establecer un nuevo valor para un control individual. El método setValue () se adhiere estrictamente a la estructura del grupo de formularios y reemplaza el valor completo del control.

  • Use el método patchValue () para reemplazar cualquier propiedad definida en el objeto que haya cambiado en el modelo de formulario.

Las verificaciones estrictas del método setValue () ayudan a detectar errores de anidamiento en formas complejas, mientras que patchValue () falla silenciosamente en esos errores.

De la documentación oficial angular aquí

por lo tanto, al actualizar el valor para una instancia de grupo de formulario que contiene múltiples controles, pero es posible que solo desee actualizar partes del modelo. patchValue () es el que estás buscando.

Veamos un ejemplo. Cuando usas patchValue ()

this.form.patchValue({
    dept: 1 
});
//here we are just updating only dept field and it will work.

pero cuando usa setValue () necesita actualizar el modelo completo ya que se adhiere estrictamente a la estructura del grupo de formularios. entonces, si escribimos

this.form.setValue({
    dept: 1 
});
// it will throw error.

Debemos pasar todas las propiedades del modelo de grupo de formulario. Me gusta esto

this.form.setValue({
      name: 'Mr. Bean'
      dept: 1,
      description: 'spome description'
  });

pero no uso este estilo con frecuencia. Prefiero usar el siguiente enfoque que ayuda a mantener mi código más limpio y más comprensible.

Lo que hago es declarar todos los controles como una variable separada y usar setValue () para actualizar ese control específico.

para el formulario anterior, haré algo como esto.

get companyIdentifier(): FormControl {
    return this.form.get('name') as FormControl;
}

get dept(): FormControl {
    return this.form.get('dept') as FormControl;
}

get description(): FormControl {
    return this.form.get('description') as FormControl;
}

cuando necesite actualizar el control de formulario, simplemente use esa propiedad para actualizarlo. En el ejemplo, el interlocutor intentó actualizar el control de formulario del departamento cuando el usuario selecciona un elemento de la lista desplegable.

deptSelected(selected: { id: string; text: string }) {
  console.log(selected) // Shows proper selection!

  // instead of using this.form.controls['dept'].setValue(selected.id), I prefer the following.

  this.dept.setValue(selected.id); // this.dept is the property that returns the 'dept' FormControl of the form.
}

Sugiero echar un vistazo a la API FormGroup para conocer todas las propiedades y métodos de FormGroup.

Adicional : para conocer getter ver aquí


1

Si está utilizando el control de formulario, entonces la forma más sencilla de hacerlo:

this.FormName.get('ControlName').setValue(value);

-1

Sugerencia: Si está utilizando setValuepero no proporciona todas las propiedades en el formulario, obtendrá un error:

Must supply a value for form control with name: 'stateOrProvince'.

Por lo tanto, puede tener la tentación de usar patchValue, pero esto puede ser peligroso si está tratando de actualizar un formulario completo. Tengo un addressque puede no tener stateOrProvinceostateCd dependiendo de si es de EE. UU. O de todo el mundo.

En su lugar, puede actualizar de esta manera, lo que utilizará los valores nulos como valores predeterminados:

this.form.setValue( { stateOrProvince: null, stateCd: null, ...address } );
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.