Définir manuellement la valeur du contrôle FormBuilder

176

Cela me rend fou, je suis sous le coup et je ne peux pas me permettre de passer une autre journée entière là-dessus.

J'essaie de définir manuellement une valeur de contrôle («dept») dans le composant, et cela ne fonctionne tout simplement pas - même la nouvelle valeur se connecte correctement.

Voici l'instance FormBuilder:

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

C'est le gestionnaire d'événements qui reçoit le service sélectionné:

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

Maintenant, lorsque le formulaire est soumis et que je me déconnecte, this.formle champ est toujours vide! J'ai vu d'autres utilisateurs utiliser updateValue()mais c'est beta.1 et je ne vois pas cela comme une méthode valide pour appeler le contrôle.

J'ai également essayé d'appeler updateValueAndValidity()sans succès :(.

Je voudrais simplement utiliser ngControl="dept"l'élément de formulaire, comme je le fais avec le reste du formulaire, mais c'est une directive / un composant personnalisé.

<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>
Matthew Brown
la source
J'avais rencontré une situation similaire, le scénario était que la valeur était définie dans http.get-subscribe et charge la valeur du formulaire, mais en définissant la ligne de valeur exécutée en premier, l'abonnement est vraiment exécuté plus tard car il est asynchrone. donc définir la valeur dans l'abonnement assurez-vous que son ensemble. my2cents!
HydTechie

Réponses:

326

Mis à jour: 19/03/2017

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

VIEUX:

Pour l'instant, nous sommes obligés de faire un cast de type:

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

Pas très élégant je suis d'accord. J'espère que cela sera amélioré dans les versions futures.

Filoche
la source
6
Cela fonctionne bien, merci. Il faut également effacer la validation: (<Control>this.form.controls['dept']).setErrors(null)
Man Called Haney
17
Ou encore this.form.get('dept').setValue(selected.id):)
developer033
6
Juste une note. Vous pouvez également accéder directement à la propriété sans indexeur. this.form.controls.dept.setValue(selected.id);
James Poulose
mais cela n'exécutera pas la validation des nouvelles données !! Comment déclencher manuellement la détection des modifications après la mise à jour?
ksh
1
C'est 2019 pour moi cela fonctionne:this.form.controls['dept'].setValue(selected.id);
John Lopez
98

Dans Angular 2 Final (RC5 +), de nouvelles API permettent de mettre à jour les valeurs de formulaire. La patchValue()méthode API prend en charge les mises à jour partielles de formulaire, où nous n'avons besoin de spécifier que certains des champs:

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

Il existe également la setValue()méthode API qui nécessite un objet avec tous les champs du formulaire. S'il manque un champ, nous obtiendrons une erreur.

Université angulaire
la source
7
Juste pour ajouter qu'à partir de maintenant updateValue(de la réponse acceptée par Filoche) est obsolète en faveur desetValue
superjos
2
Voici la demande de tirage officielle sur Github et la justification de la dépréciation updateValue()et de l'introduction de patchValueet setValue.
TheBrockEllis
mais cela n'exécutera pas la validation des nouvelles données !! Comment déclencher manuellement la détection des modifications après la mise à jour
KSH
16

Aangular 2 final a mis à jour les API. Ils ont ajouté de nombreuses méthodes pour cela.

Pour mettre à jour le contrôle de formulaire à partir du contrôleur, procédez comme suit:

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

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

Pas besoin de réinitialiser les erreurs

Références

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

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

tanveer ahmad dar
la source
différence entre les deux - setValue()lorsqu'il est appelé sur a formGroup/formBuilder, il nécessite que toutes les valeurs du formulaire soient définies. patchValue(), lorsqu'il est appelé sur le même, pourrait être utilisé pour mettre à jour des valeurs spécifiques.
Vibhor Dube
11

Vous pouvez utiliser les méthodes suivantes pour mettre à jour la valeur d'un contrôle de formulaire réactif. L'une des méthodes suivantes conviendra à vos besoins.

Méthodes utilisant setValue ()

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

Méthodes utilisant patchValue ()

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

La dernière méthode effectuera une boucle sur tous les contrôles du formulaire, elle n'est donc pas préférée lors de la mise à jour d'un contrôle unique

Vous pouvez utiliser n'importe quelle méthode à l'intérieur du gestionnaire d'événements

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

Vous pouvez mettre à jour plusieurs contrôles dans le groupe de formulaires si nécessaire à l'aide du

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

Vous pouvez essayer ceci:

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

Pour plus de détails, vous pouvez consulter le document JS correspondant concernant le deuxième paramètre de la updateValueméthode: https://github.com/angular/angular/blob/master/modules/angular2/src/common/forms/model. ts # L269 .

Thierry Templier
la source
Merci pour votre réponse - cependant updateValue ne semble pas être une méthode valide dans angular2 beta.1 - Quelle version êtes-vous sur laquelle vous pouvez utiliser cette méthode?
Matthew Brown
1
Tapuscrit donne l'erreur suivante: error TS2339: Property 'updateValue' does not exist on type 'AbstractControl'. Dans ce composant, le formulaire a le type de ControlGroup. Peut-être que si je les crée individuellement avec new Control()cela, cela fonctionnerait
Matthew Brown
5

Aucun de ceux-ci n'a fonctionné pour moi. Je devais faire:

  this.myForm.get('myVal').setValue(val);
chovy
la source
La même chose s'est produite avec moi. pourquoi est-ce le cas?
Rehmanali Momin
3
  let cloneObj = Object.assign({}, this.form.getRawValue(), someClass);
  this.form.complexForm.patchValue(cloneObj);

Si vous ne souhaitez pas définir manuellement chaque champ.

robottaxes
la source
2

Solution mise à jour Angular 2 de @ Filoche. En utilisantFormControl

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

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

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

Vous pouvez également utiliser la solution @ AngularUniversity qui utilisepatchValue

zurfyx
la source
1

Je sais que la réponse est déjà donnée, mais je veux donner une brève réponse sur la façon de mettre à jour la valeur d'un formulaire afin que d'autres nouveaux arrivants puissent avoir une idée claire.

votre structure de formulaire est si parfaite pour l'utiliser comme exemple. donc, tout au long de ma réponse, je la désignerai comme la forme.

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

donc notre formulaire est un FormGroup type d'objet qui a trois FormControl .

Il existe deux façons de mettre à jour la valeur du modèle:

  • Utilisez la méthode setValue () pour définir une nouvelle valeur pour un contrôle individuel. La méthode setValue () adhère strictement à la structure du groupe de formulaires et remplace la valeur entière du contrôle.

  • Utilisez la méthode patchValue () pour remplacer toutes les propriétés définies dans l'objet qui ont changé dans le modèle de formulaire.

Les contrôles stricts de la méthode setValue () aident à détecter les erreurs d'imbrication dans des formulaires complexes, tandis que patchValue () échoue silencieusement sur ces erreurs.

De la documentation officielle Angular ici

Ainsi, lors de la mise à jour de la valeur d'une instance de groupe de formulaires qui contient plusieurs contrôles, mais vous souhaiterez peut-être uniquement mettre à jour des parties du modèle. patchValue () est celui que vous recherchez.

voyons l'exemple. Lorsque vous utilisez patchValue ()

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

mais lorsque vous utilisez setValue (), vous devez mettre à jour le modèle complet car il adhère strictement à la structure du groupe de formulaires. alors, si nous écrivons

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

Nous devons transmettre toutes les propriétés du modèle de groupe de formulaires. comme ça

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

mais je n'utilise pas ce style fréquemment. Je préfère utiliser l'approche suivante qui aide à garder mon code plus propre et plus compréhensible.

Ce que je fais, c'est que je déclare tous les contrôles comme une variable séparée et j'utilise setValue () pour mettre à jour ce contrôle spécifique.

pour le formulaire ci-dessus, je vais faire quelque chose comme ça.

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

lorsque vous devez mettre à jour le contrôle de formulaire, utilisez simplement cette propriété pour le mettre à jour. Dans l'exemple, l'interrogateur a essayé de mettre à jour le contrôle de formulaire de service lorsque l'utilisateur sélectionnait un élément dans la liste déroulante.

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.
}

Je suggère de jeter un œil à l' API FormGroup pour connaître toutes les propriétés et méthodes de FormGroup.

Supplémentaire : pour en savoir plus sur getter voir ici

Sadid Khan
la source
1

Si vous utilisez le contrôle de formulaire, le moyen le plus simple de le faire:

this.FormName.get('ControlName').setValue(value);
Raihan Ridoy
la source
-1

Conseil: si vous utilisez setValuemais ne fournissez pas toutes les propriétés du formulaire, vous obtiendrez une erreur:

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

Vous pourriez donc être tenté d'utiliser patchValue, mais cela peut être dangereux si vous essayez de mettre à jour un formulaire entier. J'ai un addressqui peut ne pas avoir stateOrProvinceou stateCdselon qu'il s'agit des États-Unis ou du monde entier.

Au lieu de cela, vous pouvez mettre à jour comme ceci - qui utilisera les valeurs nulles par défaut:

this.form.setValue( { stateOrProvince: null, stateCd: null, ...address } );
Simon_Weaver
la source