How to initialize form group in Angular 4?
Asked Answered
T

1

10

I have the following ngOnInit method:

ngOnInit() {
    this.countries = this.sharedService.getCountries();
    this.shopService.getCurrentShopFromCache().then(shop => {
        this.shop = shop;
        this.myFormGroup = this.fb.group({
            name: [this.shop.name[this.shop.defaultLanguage.code], [Validators.required]],
            address: [this.shop.address.address],
            city: [this.shop.address.city],
            state: [this.shop.address.state],
            country: [this.shop.address.country, [Validators.required]],
            phone: [this.shop.phone],
            email: [this.shop.email],
            website: [this.shop.social.website],
            twitter: [this.shop.social.twitter],
            facebook: [this.shop.social.facebook],
            instagram: [this.shop.social.instagram],
            foursquare: [this.shop.social.foursquare]
        });
    }
    );
}

I'm getting

formGroup expects a FormGroup instance. Please pass one in.

Where am I wrong?

UPDATE:

 <form *ngIf="shop" class="m-form m-form--fit m-form--label-align-right" [formGroup]="myFormGroup" novalidate>
                       ... 
Tighe answered 16/10, 2017 at 14:45 Comment(6)
Please add template. Seems myFormGroup is undefined at first timeMidyear
I added the form tagTighe
Have you tried to debug it?Midyear
Sure. I couldn't find the way. Where should I instantiate the formGroup?Tighe
I tried again with a shop that has address.address value and the problem was solved. So how to initialize the form with some null fields?Tighe
Try to create simple form. Your code looks goodMidyear
P
24

You have to instantiate formgroup immediately on component creation, i.e. in the constructor, otherwise angular just cannot find what to bind template properties to.

UPDATE

Rephrasing: you have to instantiate form group before template gets rendered by angular. It's stricter than angular 1.x and throws an error if it cannot evaluate expression in template binding at the time of html form rendering.

Since you're using *ngIf="shop" in the template I'd say it means that shop turns not null before then() gets executed - maybe initially, maybe by some other function - it's not in the code you provided, so I can't point it out.

What you're trying to do is to initialize form with some data fetched by some service. That's totally fine - but it's still no reason to postpone creation of controls. Just create them in the constructor and set values later in the ngOnInit using FormGroup's setValue(), patchValue() or reset() - depending on what exactly you need. Below is just the idea, you'll need to adjust it to your form structure.

app.component.ts

import {Component, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

    formGroup: FormGroup;

    constructor(fb: FormBuilder) {
        this.formGroup = fb.group({
            title: fb.control('initial value', Validators.required)
        });
    }

    ngOnInit(): void {
        this.formGroup.reset({title: 'new value'});
    }

}

app.component.html

<form [formGroup]="formGroup">
    <input type="text" formControlName="title">
</form>
Punchboard answered 16/10, 2017 at 15:17 Comment(4)
You have to instantiate formgroup immediately on component creation Why? I think his code should work plnkr.co/edit/UwBTLPDAblb5ja33ZHwr?p=preview angular just cannot find what to bind template properties Angular will bind properties as soon as ngIf becames trueMidyear
@yurzui, because I missed that ngIf. :( You're right, I'll update my answer to reflect that. Still, at any point in time form group must exist before template gets rendered by angular - in this case as soon as "shop" turns to be "truthy". So yes, there should be something else wrong with OP's code - probably because "shop" is not null initially or gets filled up by something else before that async call finishes and creates form group... and angular does try to render this form without form group.Punchboard
You can use patchValue or any other function in place of reset mentioned here - angular.io/api/forms/FormGroup#methodsSkiest
Instead of assigning the value in the constructor, assign it when you create the variable. Makes the code easier to understand.Zoophyte

© 2022 - 2024 — McMap. All rights reserved.