BlueM
BlueM

Reputation: 3861

Angular2: Form Build + asynchronous data loading

I have a form created using Form Builder (Angular2 Beta 1, TypoScript), i.e.: there’s something like this in constructor:

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

The form shows up, everything is nice so far. What I don’t really get is how I handle the binding when I load the data (in this case: a User object) from a remote service (or some other asynchronous loading mechanism).

What I have tried, is:

I guess there must be some smarter/better way to get this working? I’m rather new to Angular2, so I hope the question is not too dumb …

---- Update ----

First, I forgot to mention that I use ngFormModel in the form – in case it’s important.

And @Thierry: I think that “temporary empty object to bind with the form” is what I tried to do (the 3rd approach mentioned above) but what didn’t work. Precisely, I tried this:

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

This displays the username, but it doesn’t even work when I move the line which sets this.user.username to the end of the constructor – which I find pretty surprising, as I would have expected data binding to take care of this.

Upvotes: 10

Views: 9507

Answers (4)

dfsq
dfsq

Reputation: 193291

You could also update individual controls in the FormGroup after data is loaded. For example:

this._http.get('/user/123')
    .map(response => response.json())
    .subscribe(user => {
        this.form.find('username').updateValue(user.username);
        this.form.find('email').updateValue(user.email);
    })

Important part is that you can find control instance in the formGroup one and update its value. Or simple

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

would also work.

UPD. Note that in recent versions API has changed so you need to access username with getter:

this.form.get('username').setValue(user.username)

Upvotes: 5

jfreire
jfreire

Reputation: 41

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

Upvotes: 0

Thierry Templier
Thierry Templier

Reputation: 202276

I see several solutions to this:

  • Leverage an *ngIf to display the form only when the data are there
  • Leverage the @CanActivate decorator (if you use routing) to display the component where the form is, only when data are there
  • Use a temporary empty object to bind with the form. When the data are there, you can fill (or override) this object with the data received.

Here is a plunkr: https://plnkr.co/edit/metUkOB7Sqfyr9DtCLR0?p=preview.

Hope it helps you, Thierry

Upvotes: 6

Vlado Tesanovic
Vlado Tesanovic

Reputation: 6424

You can separate your username and email in Control object, than append it to form. You will have more control with that ( you can update it later ).

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

Upvotes: 6

Related Questions