Angular2-Sollwert für formGroup

86

Ich habe also ein komplexes Formular zum Erstellen einer Entität und möchte es auch zum Bearbeiten verwenden. Ich verwende die neue API für eckige Formulare. Ich habe das Formular genau so strukturiert, wie die Daten, die ich aus der Datenbank abrufe. Daher möchte ich den Wert des gesamten Formulars auf die hier abgerufenen Daten festlegen. Dies ist ein Beispiel für das, was ich tun möchte:

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 funktioniert nicht mit neuen Formular-APIs. Außerdem macht es mir nichts aus, die Einweg-Datenbindung in der Vorlage wie in zu verwenden

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

das funktioniert, aber es wäre ein Schmerz im Fall der Arrays

Amgad Serry
quelle
Soweit ich weiß, wird das Festlegen eines Formularwerts derzeit nicht unterstützt und wird nach dem nächsten Update (RC.5) unterstützt. Bitte stellen Sie einen Plunker zur Verfügung.
Günter Zöchbauer
@ GünterZöchbauer überprüfen Sie meine aktuelle Lösung
Amgad Serry
Sehen Sie sich Folgendes an: github.com/angular/angular/blob/2.0.0-rc.5/modules/%40angular/… Zeile 553 FormGroup.setValue ()?
Clement

Antworten:

282

Um alle FormGroup-Werte festzulegen, verwenden Sie setValue :

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

Verwenden Sie patchValue, um nur einige Werte festzulegen :

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

Bei dieser zweiten Technik müssen nicht alle Werte angegeben werden, und Felder, deren Werte nicht festgelegt wurden, werden nicht beeinflusst.

Stephen Paul
quelle
1
Ich verwende patchValue in einem verschachtelten Formular und es überschreibt alle Felder im Formular. (auch die, die ich nicht spezifiziere) eine Idee, was ich falsch mache?
Enrico
9

Für den festgelegten Wert, wenn Ihr Steuerelement FormGroup ist, kann dieses Beispiel verwendet werden

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

Ja, Sie können setValue verwenden, um den Wert für Bearbeitungs- / Aktualisierungszwecke festzulegen.

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

Unter http://musttoknow.com/use-angular-reactive-form-addinsert-update-data-using-setvalue-setpatch/ finden Sie Informationen zur Verwendung von Reactive Forms zum Hinzufügen / Bearbeiten von Funktionen mithilfe von setValue. Das hat mir Zeit gespart

Prashant M Bhavsar
quelle
5

Sie können form.get verwenden, um das spezifische Steuerobjekt abzurufen und setValue zu verwenden

this.form.get(<formControlName>).setValue(<newValue>);
Varadhan Arbeit
quelle
3

Wie in den Kommentaren erwähnt, wurde diese Funktion zum Zeitpunkt der Beantwortung dieser Frage nicht unterstützt. Dieses Problem wurde in Winkel 2 rc5 behoben

Amgad Serry
quelle
2

Ich habe eine temporäre Lösung implementiert, bis Angular2 das Formular updateValue unterstützt

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

Verwendung:

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

Hinweis: Form und Daten müssen die gleiche Struktur haben und ich habe lodash zum Deepcloning von jQuery verwendet und andere Bibliotheken können dies auch

Amgad Serry
quelle
0

"NgModel funktioniert nicht mit neuen Formularen API".

Das ist nicht wahr. Sie müssen es nur richtig verwenden. Wenn Sie die reaktiven Formen verwenden, sollte das NgModel zusammen mit der reaktiven Direktive verwendet werden. Siehe das Beispiel in der Quelle .

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

Obwohl es aus den TODO-Kommentaren hervorgeht , wird dies wahrscheinlich entfernt und durch eine reaktive API ersetzt.

// TODO(kara):  Replace ngModel with reactive API
@Input('ngModel') model: any;
Paul Samsotha
quelle
NgModel-Selektor [ngModel]: not ([formControlName]): not ([formControl]) angle.io/docs/ts/latest/api/forms/index/… , selbst wenn es jetzt funktioniert, wird es so sein später entfernt Ich denke, ich werde einen manuellen Wert Injektor implementieren, da es eine stabilere Lösung sein wird
Amgad Serry
@AmgadSerry, um sicherzustellen, dass diese Komponenten nicht gestört werden (im Selektor). Das FormControlNamefügt es explizit als hinzu @Input(). Siehe die Quelle, auf die ich verlinkt habe. Wenn diese negierenden Selektoren nicht vorhanden wären, würde mit dem obigen Beispiel ein NgModel erstellt, das Sie nicht möchten.
Paul Samsotha
Es ist ein wenig verwirrend, aber genau so wird es implementiert. So funktioniert es sowohl für FormControlDirective( [formControl]) als auch für FormControlName( formControlName). Wenn das ngModelohne eines davon verwendet wird, wird davon ausgegangen, dass Sie deklarative Formulare verwenden, und es wird ein NgModelerstellt. Wenn das ngModelverwendet wird , neben einem der reaktiven Form Richtlinien, dann , dass reaktive Form Richtlinie wird das Modell handhaben , nicht einNgModel
Paul Samsotha
Oh, ich dachte, sie haben das als Hack gemacht, um ngModel nur für diese beiden Anweisungen zu aktivieren, und sie werden es später entfernen
Amgad Serry
Überprüfen Sie meine aktuelle Lösung
Amgad Serry