Wartość ustawienia Angular2 dla formGroup

91

Mam więc złożony formularz do tworzenia encji i chcę go również użyć do edycji. Używam nowego API formularzy kątowych. Skonstruowałem formularz dokładnie tak, jak dane, które pobieram z bazy danych, więc chcę ustawić wartość całego formularza na dane pobrane tutaj jest przykładem tego, co chcę zrobić:

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 nie działa z nowymi formularzami API, również nie mam nic przeciwko używaniu jednokierunkowego wiązania danych w szablonie, jak w

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

to działa, ale w przypadku tablic byłoby to uciążliwe

Amgad Serry
źródło
O ile wiem, ustawianie wartości formularzy nie jest obecnie obsługiwane i będzie obsługiwane po następnej aktualizacji (RC.5). Podaj Plunkera.
Günter Zöchbauer
@ GünterZöchbauer sprawdź moje obecne rozwiązanie
Amgad Serry
Czy patrzysz na: github.com/angular/angular/blob/2.0.0-rc.5/modules/%40angular/… line 553 FormGroup.setValue ()?
Clement

Odpowiedzi:

298

Aby ustawić wszystkie wartości FormGroup , setValue :

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

Aby ustawić tylko niektóre wartości, użyj patchValue :

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

W przypadku tej drugiej techniki nie trzeba podawać wszystkich wartości, a pola, których wartości nie zostały ustawione, nie zostaną zmienione.

Stephen Paul
źródło
1
Używam patchValue w formie zagnieżdżonej i nadpisuje wszystkie pola w formularzu. (nawet tych, których nie określam) nie masz pojęcia, co robię źle?
Enrico,
9

W przypadku wartości ustawionej, gdy formant jest FormGroup, można użyć tego przykładu

this.clientForm.controls['location'].setValue({
      latitude: position.coords.latitude,
      longitude: position.coords.longitude
    });
Sergiy Voytovych
źródło
5

Możesz użyć form.get, aby uzyskać określony obiekt kontrolny i użyć setValue

this.form.get(<formControlName>).setValue(<newValue>);
Varadhan Work
źródło
3

Jak wskazano w komentarzach, ta funkcja nie była obsługiwana w momencie zadawania tego pytania. Ten problem został rozwiązany w Angular 2 rc5

Amgad Serry
źródło
2

Zaimplementowałem tymczasowe rozwiązanie do czasu wsparcia formularza 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);
  }

stosowanie:

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

Uwaga: formularz i dane muszą mieć tę samą strukturę i użyłem lodash do głębokiego klonowania jQuery i inne biblioteki również mogą to zrobić

Amgad Serry
źródło
0

„NgModel nie działa z nowym interfejsem API formularzy”.

To nieprawda. Wystarczy, że użyjesz go poprawnie. Jeśli korzystasz z formularzy reaktywnych, NgModel powinien być używany zgodnie z dyrektywą reaktywną. Zobacz przykład w źródle .

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

Chociaż wygląda na to z komentarzy do TODO , prawdopodobnie zostanie to usunięte i zastąpione reaktywnym interfejsem API.

// TODO(kara):  Replace ngModel with reactive API
@Input('ngModel') model: any;
Paul Samsotha
źródło
pochodzące z angular2 api docs Selektor NgModel [ngModel]: not ([formControlName]): not ([formControl]) angular.io/docs/ts/latest/api/forms/index/... więc nawet jeśli teraz zadziała, będzie usunięte później myślę, że zaimplementuję wtryskiwacz ręczny, ponieważ będzie to bardziej stabilne rozwiązanie
Amgad Serry
@AmgadSerry, aby upewnić się, że nie koliduje z tymi komponentami (w selektorze). FormControlNameWyraźnie dodaje go jako @Input(). Zobacz źródło, z którym się łączyłem. Gdyby nie było tych wykluczających selektorów, to w powyższym przykładzie zostałby utworzony NgModel, którego nie chcesz.
Paul Samsotha
To trochę zagmatwane, ale tak właśnie jest zaimplementowane. Tak to działa zarówno w przypadku FormControlDirective( [formControl]), jak i FormControlName( formControlName). Jeśli ngModeljest używany bez jednego z nich, zakłada się, że będziesz używać deklaratywnych formularzy i NgModelzostanie utworzony plik . Jeśli ngModeljest używane razem z jedną z dyrektyw form reaktywnych , to ta dyrektywa formy reaktywnej będzie obsługiwać model, a nieNgModel
Paul Samsotha
och, myślałem, że zrobili to jako hack, aby włączyć ngModel na tych dwóch dyrektywach tylko na razie i usuną go później
Amgad Serry
sprawdź moje obecne rozwiązanie
Amgad Serry