formGroup expects a FormGroup instance. Please pass one in


#1

I am new to ionic2 making an app.when adding form validation facing an error “formGroup expects a FormGroup instance. Please pass one in

signup.html





Signup

Email
  <ion-item>
    <ion-label fixed>Password</ion-label>
    <ion-input type="password" name="password" [(ngModel)]="registerCredentials.password" requried></ion-input>
  </ion-item>


</ion-list>

<div padding>
  <button ion-button block  (click)="register(registerCredentials)">Sign Up</button>
</div>

signup.ts

import { Component } from ‘@angular/core’;
import { AuthService } from ‘…/…/providers/auth-service’;
import ‘rxjs/add/operator/debounceTime’;
import { NavController, AlertController, ToastController } from ‘ionic-angular’;
import { Http } from ‘@angular/http’;
import { LoginPage } from ‘…/login/login’;
import { Validators, FormGroup, FormControl} from ‘@angular/forms’;

@Component({
templateUrl: ‘signup.html’
})
export class SignupPage {
sampleForm: FormGroup;
createSuccess = false;
registerCredentials:any = {email: ‘’, password: ‘’};
constructor(private nav: NavController, private alertCtrl: AlertController, private auth: AuthService,private toastCtrl: ToastController, public http : Http) {}

 ionViewDidLoad() {

      this.sampleForm = new FormGroup({
           email: new FormControl('', Validators.compose([
                Validators.required,
                Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
           ])),
           password: new FormControl('', Validators.compose([
   Validators.minLength(5),
   Validators.required,
   Validators.pattern('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]+$')
]))

 })

this.sampleForm.valueChanges
.debounceTime(400)
.subscribe(data => this.onValueChanged(data));
}

onValueChanged(data?: any) {
if (!this.sampleForm) { return; }
const form = this.sampleForm;
for (const field in this.formErrors) {
// clear previous error message
this.formErrors[field] = [];
this.sampleForm[field] = ‘’;
const control = form.get(field);
if (control && control.dirty && !control.valid) {
const messages = this.validationMessages[field];
for (const key in control.errors) {
this.formErrors[field].push(messages[key]);
}
}
}
}

formErrors = {
‘email’: [],
‘password’: []
};

validationMessages = {
‘email’: {
‘required’: ‘Email is required’,
‘pattern’: ‘Enter a valid email.’
},
‘password’: {
‘required’: ‘Password is required’,
‘minlength’: ‘Password must be at least 5 characters long.’,
‘pattern’: ‘Your password must contain at least one uppercase, one lowercase, and one number.’
}
};

           register(registerCredentials){
                // console.log('hello');
                // this.http.post('http://10.20.1.166:3000/users/register').map(res => res.json()).subscribe(response => {console.log('success')});

                this.auth.register(registerCredentials).subscribe(response => {
                     if(response.resStatus == 'success') {
                          this.createSuccess = true;
                          // this.showPopup("Success", "Account created.");
                          // console.log('response'+response.resStatus);
                          let toast = this.toastCtrl.create({
                               message: 'Account created successfully',
                               duration: 3000,
                               position: 'top'
                          });
                          toast.present();
                          this.nav.setRoot(LoginPage);
                     } else {

                     }

                })
           }


      }

#2

According to your component, the template should reference sampleForm:

<form [formGroup]="sampleForm" #registerForm="ngForm">

#3

Also move the FormGroup code into the constructor.


#4

I had this issue the problem here is that the form is being called way to quick before the initialisation in the ionViewLoaded is happening. As soon as you move it to the constructor it works properly. Also, the same code in a normal NG2 app works in the ngOnInit is this a Bug or something else?


#5

@saniyusuf Replace ionViewLoaded by ionViewDidLoad since the former valid lifecycle event anymore. I made the same error since I used the official (out of date) documentation as a reference.


#6

I meant IonViewDidLoad actually still it is being called in the view before it is instantiated. I moved mine to the constructor but in essence the ngOnInit should be very close in timing with ionViewDidLoad . In this case, it is not.


#7

Hello all, the docs section Forms with FormBuilder should read like this:

import { Component } from '@angular/core';
import {FormGroup, FormBuilder, Validators} from '@angular/forms';
@Component({
  template: `
    <form [formGroup]="todo" (ngSubmit)="logForm()">
      <ion-item>
        <ion-label>Todo</ion-label>
        <ion-input type="text" formControlName="title"></ion-input>
      </ion-item>
      <ion-item>
        <ion-label>Description</ion-label>
        <ion-textarea formControlName="description"></ion-textarea>
      </ion-item>
      <button ion-button type="submit" [disabled]="!todo.valid">Submit</button>
    </form>
  `
})
export class FormsPage {
  todo: FormGroup;
  constructor(private formBuilder: FormBuilder) {
    this.todo = this.formBuilder.group({
      title: ['', [Validators.required, Validators.minLength(5)]],
      description: [''],
    });
    this.todo.valueChanges.subscribe(data=>this.todoOnDataChange(data));
  }
  todoOnDataChange(data: any): void {
     console.log(data);
  }
  logForm(){
    console.log(this.todo.value)
  }
}

:slight_smile: cheers!


#8

Agreed. I also couldn’t get this to work with formBuilder.create() in ionViewDidLoad() but it works in the constructor.


#9

Im also see this error after I literally copied the code from docs section. Its driving me nuts. Anyone got any idea how to solve it. Here is my code

import { NgModule, OnInit } from '@angular/core';
import { IonicPageModule, NavController } from 'ionic-angular';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { LoginPage } from './LoginPage';

@NgModule({
  declarations: [
    LoginPage,
  ],
  imports: [
    IonicPageModule.forChild(LoginPage),
  ],
  exports: [
    LoginPage
  ]
})
export class LoginPageModule{

  loginForm: FormGroup;

  constructor(private formBuilder: FormBuilder) {  
        this.loginForm = this.formBuilder.group({
          email: ['', [Validators.maxLength(140), Validators.required]], 
          password: ['', [Validators.minLength(6), Validators.required]],
        })
  }

And my very simple template:

<ion-content padding>
    <form [formGroup]="loginForm" (ngSubmit)="loginUser()">
        <ion-item>
            <ion-label>Email</ion-label>
            <ion-input formControlName="email" type="email"></ion-input>
        </ion-item>

        <ion-item>
            <ion-label>Password</ion-label>
            <ion-input #password formControlName="password" type="password"></ion-input>
        </ion-item>
    </form>
</ion-content>

#10

Whoa there. What docs section suggested you create that unholy mashup of a module and a component? I’ve never seen anything like that before.