2016-02-03 3 views
9

Ich habe ein Formular erstellt Form Builder (Angular2 Beta 1, TypoScript), dh: es gibt so etwas wie dieses ist in constructor:Angular2: Form Bauen + asynchrone Datenlade

this.form = this._formBuilder.group({ 
    'username': ['', Validators.required], 
    'email': ['', Validators.required] 
}); 

Die Form nach oben zeigt, ist alles Nett so weit. Was ich nicht wirklich wirklich bekomme ist, wie ich die Bindung handhabe, wenn ich die Daten (in diesem Fall ein Benutzerobjekt) von einem Remote-Dienst (oder einem anderen asynchronen Lademechanismus) lade.

Was ich versucht habe, ist:

  • laden die Daten asynchron in constructor oder ngOnInit. Problem: löst eine Ausnahme aus, noch bevor das Laden beginnt ("Eigenschaft kann nicht gelesen werden" von undefiniertem ... ")
  • Laden Sie die Daten asynchron in constructor oder ngOnInit, aber erstellen Sie zuvor ein leeres Formular. Problem: Validierung funktioniert nicht.
  • Was hätte ich erwartet zu arbeiten: Binden Sie die Formulardaten an Eigenschaften eines User Objekts, und legen Sie die Eigenschaften dieses Objekts fest. Problem: keine Ausnahme, aber die Daten werden nicht im Formular angezeigt.

Ich denke, es muss einen klüger/besseren Weg, um dies funktioniert zu bekommen? Ich bin ziemlich neu zu Angular2, so dass ich hoffe, dass die Frage nicht zu dumm ist ...

---- ---- aktualisiert

Zuerst habe ich vergessen zu erwähnen, dass ich ngFormModel in Form verwenden - in Fall ist es wichtig.

Und @ Thierry: Ich denke, dass "temporäre leeres Objekt mit der Form zu binden" ist, was ich versucht habe zu tun (der dritte Ansatz oben erwähnt), aber was nicht funktioniert. Gerade habe ich versucht, dies:

constructor(private _formBuilder:FormBuilder) { 
    this.user = new User; 
    this.user.username = 'abc'; 
    this.form = this._formBuilder.group({ 
     'username': [this.user.username, Validators.required], 
    }); 
} 

Dies zeigt den Benutzername, aber es funktioniert nicht einmal arbeiten, wenn ich die Linie bewegen, die this.user.username bis zum Ende des Konstrukteurs setzt - was ich ziemlich überraschend zu finden, wie ich hätte erwartete Datenbindung, um sich darum zu kümmern.

+0

Sind Sie sicher für das temporäre leere Objekt? ;-) Siehe mein Plunkr: https://plnrkr.co/edit/metUkOB7Sqfyr9DtCLR0?p=preview. Die Validierung funktioniert auch nach dem Laden der Daten ... –

+0

Interessant. Vielleicht ist dies ein Problem von "Template Driven" vs "Model Driven" Ang2 Formen. Ich benutze den letzteren Ansatz und habe kein '[(ngModel)]' in der Steuerung - könnte das der Grund dafür sein, dass es hier nicht funktioniert hat? – BlueM

+0

Ja, ich verwende auch einen modellgesteuerten Ansatz. Ohne 'ngModel' müssen Sie alle Kontrollwerte von Hand setzen ... Das ist bei 'ngModel' nicht der Fall: Aktualisieren Sie das globale Objekt und alle gebundenen Eigenschaften werden automatisch aktualisiert ;-) –

Antwort

6

Sie Ihren Benutzernamen und E-Mail in Control-Objekt trennen kann, als hängen Sie ihn zu bilden. Sie haben damit mehr Kontrolle (Sie können es später aktualisieren).

form: ControlGroup; 
email: Control = new Control(""); 
name: Control = new Control(""); 
constructor(public fb: FormBuilder) { 
this.form = fb.group({ 
     email: this.email, 
     name: this.name 
    }); 

    setTimeout(() => { 
     this.email.updateValue("invalid email"); 
     this.name.updateValue("Name"); 
    }, 3000); 
} 

Plunker example

+0

Die Trennung war der Schlüssel. Danke. – BlueM

5

Ich sehe mehrere Lösungen für diese:

  • Leverage eine *ngIf das Formular anzuzeigen nur dann, wenn die Daten dort
  • Nutzen Sie die @CanActivate Dekorateur (wenn Sie Routing verwenden), um die Komponente anzuzeigen, in dem die Form ist, nur wenn Daten vorhanden sind
  • Verwenden Sie ein temporäres leeres Objekt, um mit dem Formular zu binden. Wenn die Daten vorhanden sind, können Sie dieses Objekt mit den empfangenen Daten füllen (oder überschreiben).

Hier ist ein Plunkr: https://plnkr.co/edit/metUkOB7Sqfyr9DtCLR0?p=preview.

Hoffe, es hilft Ihnen, Thierry

4

Sie auch einzelne Kontrollen im FormGroup aktualisieren können, nachdem die Daten geladen wird. Zum Beispiel:

Wichtiger Teil ist, dass Sie Kontrollinstanz in der FormGroup eins finden und seinen Wert aktualisieren können. Oder einfach

this.form.controls.username.updateValue(user.username) 

würde auch funktionieren.

+0

Auch gut zu wissen. Für mich sieht das sehr elegant aus. – BlueM

+0

Muss ich richtigerweise davon ausgehen, dass dies auch den Wert in der Ansicht aktualisiert? – brando

+0

@Brando ja, natürlich. – dfsq

0

Verwendung this.form.setValues({username: this.user.username, mail: this.user.mail})

+1

Hallo jfreire, und danke für die Antwort! Ihr Code könnte korrekt sein, aber mit etwas Kontext würde es eine bessere Antwort geben; Zum Beispiel könnten Sie erklären, wie und warum diese vorgeschlagene Änderung das Problem des Fragestellers lösen würde, möglicherweise einschließlich eines Links zu der relevanten Dokumentation. Das würde es für sie nützlicher machen und auch für andere Leser der Website, die nach Lösungen für ähnliche Probleme suchen. –

Verwandte Themen