Valeur définie Angular2 pour formGroup

91

J'ai donc un formulaire complexe pour créer une entité et je souhaite également l'utiliser pour l'édition. J'utilise une nouvelle API de formulaires angulaires. J'ai structuré le formulaire exactement comme les données que je récupère de la base de données, je veux donc définir la valeur de l'ensemble du formulaire sur les données récupérées.Voici un exemple de ce que je veux faire:

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 ne fonctionne pas avec les nouvelles API de formulaires et cela ne me dérange pas d'utiliser la liaison de données à sens unique dans le modèle comme dans

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

cela fonctionne mais ce serait pénible en cas de tableaux

Amgad Serry
la source
Pour autant que je sache, la définition d'une valeur de formulaire n'est actuellement pas prise en charge et sera prise en charge après la prochaine mise à jour (RC.5). Veuillez fournir un Plunker.
Günter Zöchbauer
@ GünterZöchbauer vérifier ma solution actuelle
Amgad Serry
Regardez-vous: github.com/angular/angular/blob/2.0.0-rc.5/modules/%40angular/… ligne 553 FormGroup.setValue ()?
Clement

Réponses:

298

Pour définir toutes les valeurs FormGroup, utilisez setValue :

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

Pour définir uniquement certaines valeurs, utilisez patchValue :

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

Avec cette seconde technique, toutes les valeurs n'ont pas besoin d'être fournies et les champs dont les valeurs n'ont pas été définies ne seront pas affectés.

Stephen Paul
la source
1
J'utilise patchValue dans un formulaire imbriqué et il écrase tous les champs du formulaire. (même ceux que je ne précise pas) une idée de ce que je fais mal?
Enrico
9

Pour définir la valeur lorsque votre contrôle est FormGroup, vous pouvez utiliser cet exemple

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

Oui, vous pouvez utiliser setValue pour définir la valeur à des fins d'édition / de mise à jour.

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

Vous pouvez consulter http://musttoknow.com/use-angular-reactive-form-addinsert-update-data-using-setvalue-setpatch/ pour comprendre comment utiliser les formulaires réactifs pour ajouter / modifier la fonction en utilisant setValue. Ça m'a sauvé du temps

Prashant M Bhavsar
la source
5

Vous pouvez utiliser form.get pour obtenir l'objet de contrôle spécifique et utiliser setValue

this.form.get(<formControlName>).setValue(<newValue>);
Travail de Varadhan
la source
3

Comme indiqué dans les commentaires, cette fonctionnalité n'était pas prise en charge au moment où cette question a été posée. Ce problème a été résolu dans angular 2 rc5

Amgad Serry
la source
2

J'ai implémenté une solution temporaire jusqu'à la mise à jour du formulaire de support angular2

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

Remarque: le formulaire et les données doivent avoir la même structure et j'ai utilisé lodash pour le deepcloning jQuery et d'autres bibliothèques peuvent également le faire

Amgad Serry
la source
0

"NgModel ne fonctionne pas avec les nouvelles formes d'API".

Ce n'est pas vrai. Il vous suffit de l'utiliser correctement. Si vous utilisez les formes réactives, le NgModel doit être utilisé de concert avec la directive réactive. Voir l'exemple dans la 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"
 *  }
 * }
 */

Bien que cela ressemble aux commentaires TODO , cela sera probablement supprimé et remplacé par une API réactive.

// TODO(kara):  Replace ngModel with reactive API
@Input('ngModel') model: any;
Paul Samsotha
la source
provenant de angular2 api docs NgModel selector [ngModel]: not ([formControlName]): not ([formControl]) angular.io/docs/ts/latest/api/forms/index/… donc même si cela fonctionne maintenant, il sera supprimé plus tard, je pense que je vais mettre en œuvre un injecteur de valeur manuelle car ce sera une solution plus stable
Amgad Serry
@AmgadSerry c'est pour s'assurer qu'il n'interfère pas avec ces composants (dans le sélecteur). L' FormControlNameajoute explicitement en tant que fichier @Input(). Voir la source à laquelle j'ai lié. Si ces sélecteurs de négation n'étaient pas là, alors avec l'exemple ci-dessus, un NgModel serait créé, ce que vous ne voulez pas.
Paul Samsotha
C'est un peu déroutant, mais c'est juste comme ça que c'est implémenté. Pour les deux FormControlDirective( [formControl]) et FormControlName( formControlName), voici comment cela fonctionne. Si le ngModelest utilisé sans l'un de ceux-ci, il est supposé que vous utiliserez des formulaires déclaratifs et un NgModelest créé. Si le ngModelest utilisé avec l' une des directives de formulaire réactif , alors cette directive de formulaire réactif gérera le modèle, pas unNgModel
Paul Samsotha
oh je pensais qu'ils l'avaient fait comme un hack pour activer ngModel sur ces deux directives uniquement pour le moment et ils le supprimeront plus tard
Amgad Serry
vérifier ma solution actuelle
Amgad Serry