Page not reflecting changes


#1

Hi All,

I am using Ionic2 rc4. I have a login form.

enter image description here

As you can see, the Sign In button is disabled.

My problem is it should only be disabled when the form is invalid. However, when the form is valid, i.e. there is an Email and Password, it should not be disabled.

When I enter an Email and Password it stays disabled, but if I switch focus off the browser, and then back to it, it is enabled. It is as if the page is not refreshing to the correct status.

Question

Is there a way to get this enabled immediately as the form is valid?

loginemail.html

<ion-header>
  <ion-navbar>
    <button ion-button menuToggle>
      <ion-icon name="menu"></ion-icon>
    </button>
    <ion-title>Login</ion-title>
  </ion-navbar>
</ion-header>


<ion-content padding>

  <form [formGroup]="loginForm" (ngSubmit)="submit()">
    <ion-item>
      <ion-label floating>Email</ion-label>
      <ion-input type="text" formControlName="email" id="email" [(ngModel)]="personModel.emailAddress"></ion-input>
    </ion-item>
    <control-messages class="error-box" [control]="loginForm.controls.email"></control-messages>
    <ion-item>
      <ion-label floating>Password</ion-label>
      <ion-input type="password" formControlName="password" id="password"></ion-input>
    </ion-item>
    <control-messages class="error-box" [control]="loginForm.controls.password"></control-messages>
    <br/>
    <ion-buttons>
      <button ion-button class="form-button-text" type="submit" [disabled]="!loginForm.valid" block round>Sign In</button>
    </ion-buttons>
  </form>
  <br/><br/>
  <p (click)="forgotPassword()" class="small-text">Forgot email or password?</p>
  <br/><br/><br/><br/>
  <button ion-button color="light" (click)="register()" color="dark" clear block round class="form-button-text">Quick Sign up</button>

</ion-content>

loginemail.ts

import { Component, Input, Inject, forwardRef } from '@angular/core';
import { NavController, NavParams, ViewController, AlertController, MenuController, Events, Loading, LoadingController } from 'ionic-angular';
import { FirebaseAuth } from 'angularfire2';
import { ValidationService } from '../validation/validationService';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { RegisterPage } from '../register/register';
import { ForgotPage } from '../forgot/forgot';
import { PersonModel } from '../model/personModel';
import { PersonService } from '../service/personService';
import { UtilityService } from '../utils/utilityService';
import { PersonPage } from '../person/person';

@Component({
    templateUrl: 'loginemail.html'
})

export class LoginEmailPage {

    public loginForm: FormGroup;
    public errorMessage: string;
    public personModel: PersonModel = null;
    public personService: PersonService = null;
    public personLoggedIn: boolean = false;
    public menu: MenuController = null;
    public utilityService: UtilityService = null;
    public events: Events = null;
    public loading: Loading = null;
    public alertCtrl: AlertController = null;
    public fireAuth: firebase.auth.Auth;
    public userProfile: firebase.database.Reference;

    @Input() control: FormControl;

    constructor(@Inject(forwardRef(() => UtilityService)) utilityService, public auth: FirebaseAuth, menu: MenuController, public nav: NavController, 
        public navParams: NavParams, public builder: FormBuilder, public viewCtrl: ViewController, alertCtrl: AlertController, 
        personService: PersonService, events: Events, public loadingCtrl: LoadingController) {
        this.fireAuth = firebase.auth();
        this.userProfile = firebase.database().ref('/userProfile');
        this.loginForm = builder.group({
            'email': ['', [Validators.required, Validators.minLength(3), Validators.maxLength(55), ValidationService.emailValidator, (control) => ValidationService.personEmailNotExists(control, this.personService)]],
            'password': ['', [Validators.required, Validators.minLength(5), Validators.maxLength(45), ValidationService.passwordValidator]]
        });
        this.alertCtrl = alertCtrl;
        this.events = events;
        this.utilityService = utilityService;
        this.menu = menu;
        this.personModel = this.navParams.get('personModel');
        if (!this.personModel) {
            this.personModel = new PersonModel();
        }
        this.personService = personService;
    }

    submit() {
        this.loading = this.loadingCtrl.create({
            content: 'Please wait...'
        });
        if (this.loginForm.dirty && this.loginForm.valid) {
            this.loading.present().then(() => {
                this.checkCredentials(this.loginForm.value.email, this.loginForm.value.password).then(() => {
                    if (this.personLoggedIn === true) {
                        this.loginFirebaseUser(this.loginForm.value.email, this.loginForm.value.password).then((authData) => {
                            let user: firebase.User = this.fireAuth.currentUser;
                            if (!user) {
                                this.auth.subscribe((authData) => {
                                    this.login(authData.auth);
                                });
                            } else {
                                this.login(user);
                            }
                        }).catch((error) => {
                            console.error('Error trying to login ', error);
                            this.loading.dismiss().then(() => {
                                this.doAlert(error.message);
                            });
                        });
                    }
                    this.loading.dismiss();
                });
            });
        }
    }

    login(firebaseUser: firebase.User): void {
        let promise: Promise<any> = this.utilityService.login(this.personModel, firebaseUser, this.nav, this.auth, this.fireAuth, false);
        if (promise) {
            promise.then(() => {
                let data = {
                    person: this.personModel
                }
                this.events.publish('push:notifications', data);
                this.loading.dismiss().then(() => {
                    if (this.navParams.get('fromReview')) {
                        this.nav.pop();
                    } else if (this.navParams.get('fromChat')) {
                        this.nav.pop();
                    } else {
                        this.nav.setRoot(PersonPage);
                    }
                });
            }, error => {
                this.utilityService.logout(this.auth, this.fireAuth).then(() => {
                    this.utilityService.setUpMenuItems();
                    this.auth.logout();
                });
                this.loading.dismiss().then(() => {
                    let alert = this.alertCtrl.create({
                        message: error.message,
                        buttons: [
                            {
                                text: "Ok",
                                role: 'cancel'
                            }
                        ]
                    });
                    alert.present();
                });
            });
        } else {
            this.loading.dismiss();
        }
    }

    checkCredentials(email: string, password: string): any {
        let promiseUsername: Promise<PersonModel> = this.personService.getPersonByEmail(email);
        return promiseUsername.then((personModel: PersonModel) => {
            if (personModel.emailAddress != email) {
                this.doAlert('Email does not exist.');
            } else {
                if (personModel.emailAddress === this.loginForm.value.email) {
                    this.personModel = personModel;
                    this.personLoggedIn = true;
                } else {
                    this.personLoggedIn = false;
                    this.doAlert('Password does not match Username.');
                }
            }
        });
    }

    doAlert(msg: string) {
        this.loading.dismiss().then(() => {
            let alert = this.alertCtrl.create({
                title: 'Login',
                subTitle: msg,
                buttons: ['Dismiss']
            });
            alert.present().then(() => {
                this.loading.dismiss();
            });
        });
    }


    register() {
        this.nav.push(RegisterPage, {
        })
    }

    forgotPassword() {
        this.nav.push(ForgotPage, {
            personModel: this.personModel
        });
    }

    loginFirebaseUser(email: string, password: string): firebase.Promise<boolean> {
        return this.fireAuth.signInWithEmailAndPassword(email, password).then(() => {
            console.log('signInWithEmailAndPassword', email, password);
        }).catch((error)=> {
            console.error('Error signInWithEmailAndPassword', email, password, error.name, error.message);
            throw new Error(error.message);
        });
    }
}

#2

Was looking at ChangeDetectionStrategy, ChangeDetectorRef:

ref.markForCheck()

But don’t think this will work for me, because the users action is disabled due to the button being incorrectly disabled.

Or is there some way of doing it on change of focus of the input fields?