Autenticación con correo y contraseña en Ionic con Firebase – Parte 2

En el primera parte pudimos crear las pantallas que vamos a necesitar en esta aplicación y también configuramos el proyecto en Firebase. Ahora vamos a empezar a integrar Firebase en la aplicación.

AngularFire2

Como ya sabemos, Ionic utiliza Angular como framework de desarrollo, entonces vamos a utilizar AngularFire, librería oficial de Angular para Firebase, para integrarnos con Firebase.

Primero necesitamos instalar los paquetes de firebase y angularfire2 en nuestro proyecto, para ello, utilizando la consola, nos ponemos dentro de la carpeta del proyecto y ejecutamos:

npm install firebase --save
npm install angularfire2 --save

Luego vamos a modificar el módulo principal o raíz de la aplicación AppModule, que se encuentra en el archivo src/app/app.module.ts para importar el módulo de AngularFire:


import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { SignInPage } from '../pages/signin/signin';
import { SignUpPage } from '../pages/signup/signup';
export const firebaseConfig = {
apiKey: "AIzaSyA3jE_yGw17BSReFk_QMo7fuf4fSiKFW8k",
authDomain: "ionfire-df87b.firebaseapp.com",
databaseURL: "https://ionfire-df87b.firebaseio.com",
projectId: "ionfire-df87b",
storageBucket: "ionfire-df87b.appspot.com",
messagingSenderId: "783410523738"
};
@NgModule({
declarations: [
MyApp,
HomePage,
SignInPage,
SignUpPage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp),
AngularFireModule.initializeApp(firebaseConfig),
AngularFireAuthModule
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
SignInPage,
SignUpPage
],
providers: [
StatusBar,
SplashScreen,
{ provide: ErrorHandler, useClass: IonicErrorHandler }
]
})
export class AppModule { }

view raw

app.module2.ts

hosted with ❤ by GitHub

  • En las líneas 7 y 8 importamos los módulo de AngularFire que vamos a utilizar AngularFireModule y AngularFireAuthModule.
  • Empezando en la línea 15 definimos la constante firebaseConfig con las configuraciones de nuestro proyecto de Firebase, las cuales necesitamos para inicializar AngularFire (ya vamos a ver de dónde optenemos esa información).
  • Finalmente en las líneas 34 y 35 inicializamos el módulo AngularFireModule utilizando las configuraciones establecidas en la constante firebaseConfig, y adicionamos estos módulos importados a los imports de nuestro módulo AppModule, lo cual quiere decir que todos los exports (como por ejemplo clases) de estos módulos van a estar disponible en nuestro módulo.

Las configuraciones de Firebase para nuestro proyecto las podemos obtener desde la consola de Firebase. Si accedemos a la consola de Firebase y vamos a la página de “Overview” de nuestro proyecto vamos a poder ver tres opciones para adicionar Firebase a nuestras aplicaciones, una para iOS, otra para Android y finalmente una para web:

Opciones para configurar aplicaciones en Firebase
Opciones para configurar aplicaciones en Firebase

Nosotros vamos a seleccionar la opción para web, ya que nuestra aplicación, después de todo, es una “aplicación web” o utiliza tecnologías para la web. Haciendo click en dicha opción veremos la siguiente ventana:

Configuración para una aplicación web
Configuración para una aplicación web

Como vemos, aquí tenemos toda la información que necesitamos para inicializar AngularFire en nuestra aplicación.

Modelo

Vamos a crear un modelo sencillo para guardar los datos del usuario (correo y contraseña) el cual vamos a reutilizar tanto en la pantalla de inicio de sesión como en la de registro. Para ello creamos una carpeta llamada models dentro de la carpeta src y luego adicionamos el archivo src/models/user-model.ts:


export class UserModel {
email: string;
password: string;
}

view raw

user-model.ts

hosted with ❤ by GitHub

No hay mucho que comentar aquí, simplemente una clase con dos propiedades.

Proveedor de autenticación

Vamos a crear un servicio/proveedor de autenticación que sea el encargado de utilizar el API de AngularFire para realizar las funciones de autenticación que necesitamos como iniciar sesión, crear usuario, cerrar sesión y saber si un usuario está o no autenticado.

Para ello creamos una carpeta llamada providers dentro de la carpeta src y luego adicionamos el archivo src/providers/auth-service.ts:


import { Injectable } from '@angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import { User, Promise } from 'firebase/app';
import { UserModel } from '../models/user-model';
@Injectable()
export class AuthService {
user: User;
constructor(public angularFireAuth: AngularFireAuth) {
angularFireAuth.authState.subscribe((user: User) => {
this.user = user;
});
}
get authenticated(): boolean {
return this.user != null;
}
signInWithEmailAndPassword(userModel: UserModel): Promise<any> {
return this.angularFireAuth.auth.signInWithEmailAndPassword(userModel.email, userModel.password);
}
createUserWithEmailAndPassword(userModel: UserModel): Promise<any> {
return this.angularFireAuth.auth.createUserWithEmailAndPassword(userModel.email, userModel.password);
}
signOut(): Promise<any> {
return this.angularFireAuth.auth.signOut();
}
}

view raw

auth-service.ts

hosted with ❤ by GitHub

  • Importamos en la línea 3 la clase AngularFireAuth de AngularFire que nos permite acceder al API de autenticación.
  • En la siguiente línea importamos las clases User y Promise de Firebase.
  • En el constructor inyectamos una instancia de AngularFireAuth y nos suscribimos al cambio de estado de la autenticación, de este modo podemos saber cuando un usuario inicia o cierra sesión, obtener los datos básicos del usuario y guardarlos en la propiedad user que definimos en la línea 10.
  • La propieda de acceso autenticated compara la propiedad user con null, de este modo sabemos si el usuario está o no autenticado.
  • El método signInWithEmailAndPassword recibe una instancia del modelo UserModel del cual utiliza el correo y la contraseña para autenticar al usuario llamando al método de igual nombre de la propiedad auth (instancia de la clase Auth de Firebase) perteneciente a angularFireAuth.
  • El método createUserWithEmailAndPassword es muy similar al anterior sólo que este es para crear un usuario, utilizando el método de igual nombre de la propiedad auth en angularFireAuth.
  • Finalmente el método signOut() utiliza el método de igual nombre de la propiedad auth en angularFireAuth para cerrar la sesión.

Antes de poder utilizar este proveedor en nuestras páginas tenemos que hacerlo disponible, para ello, una vez más modificaremos nuestro módulo AppModule:


import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { AngularFireModule } from 'angularfire2';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AuthService } from '../providers/auth-service';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { SignInPage } from '../pages/signin/signin';
import { SignUpPage } from '../pages/signup/signup';
export const firebaseConfig = {
apiKey: "AIzaSyA3jE_yGw17BSReFk_QMo7fuf4fSiKFW8k",
authDomain: "ionfire-df87b.firebaseapp.com",
databaseURL: "https://ionfire-df87b.firebaseio.com&quot;,
projectId: "ionfire-df87b",
storageBucket: "ionfire-df87b.appspot.com",
messagingSenderId: "783410523738"
};
@NgModule({
declarations: [
MyApp,
HomePage,
SignInPage,
SignUpPage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp),
AngularFireModule.initializeApp(firebaseConfig),
AngularFireAuthModule
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
SignInPage,
SignUpPage
],
providers: [
StatusBar,
SplashScreen,
{ provide: ErrorHandler, useClass: IonicErrorHandler },
AuthService
]
})
export class AppModule { }

view raw

app.module3.ts

hosted with ❤ by GitHub

Primero lo importamos en la línea 10 y luego lo adicionamos a la lista de proveedores en la línea 50.

Registrando usuarios

Ahora si es momento de empezar a registrar usuarios en Firebase, regresando al código de la pantalla de registro en src/pages/signup/signup.ts y a la vista en src/pages/signup/signup.html:


import { Component } from '@angular/core';
import { NavController, LoadingController, AlertController } from 'ionic-angular';
import { AuthService } from '../../providers/auth-service';
import { UserModel } from '../../models/user-model';
import { SignInPage } from '../signin/signin';
@Component({
selector: 'page-signup',
templateUrl: 'signup.html'
})
export class SignUpPage {
userModel: UserModel;
constructor(
public navCtrl: NavController,
public loadingCtrl: LoadingController,
public alertCtrl: AlertController,
public authService: AuthService) {
this.userModel = new UserModel();
}
signUp() {
let loading = this.loadingCtrl.create({
content: 'Creando cuenta. Por favor, espere…'
});
loading.present();
this.authService.createUserWithEmailAndPassword(this.userModel).then(result => {
loading.dismiss();
this.navCtrl.push(SignInPage);
}).catch(error => {
loading.dismiss();
console.log(error);
this.alert('Error', 'Ha ocurrido un error inesperado. Por favor intente nuevamente.');
});
}
alert(title: string, message: string) {
let alert = this.alertCtrl.create({
title: title,
subTitle: message,
buttons: ['OK']
});
alert.present();
}
}

view raw

signup2.ts

hosted with ❤ by GitHub

Muchos de los cambios realizados son cambios sencillos relacionados tanto a Angular como a Ionic como importar la página de inicio de sesión, el modelo UserModel y el proveedor AuthService, inyectar servicios a través del constructor, mostrar una alerta, etc., vamos a ver en detalles el métido signup().

Cuando se ejecuta el método signup() vamos a mostrar una ventana de “cargando” mientras estemos registrando al usuario, luego utilizamos el servicio AuthService que inyectamos en el constructor para ejecutar su método createUserWithEmailAndPassword() el cual recibe el modelo UserModel el cual ya va a tener los datos del usuario capturados en la vista (como veremos a continuación), este método devuelve una promesa por lo que en el then() the la promesa vamos a suponer que el usuario fue registrado por lo que enviamos al usuario a la pantalla de inicio de sesión para que pueda utilizar sus nuevas credenciales y entrar en la aplicación; de lo contrario, en el catch() vamos mostrar una alerta de error. En ambos casos primamente cerramos la ventana de “cargando” utilizando con la llamada loading.dismiss();.


<ion-header>
<ion-navbar>
<ion-title>Registrarse</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<form #signUpForm="ngForm" (submit)="signUp()">
<ion-list>
<ion-item>
<ion-label stacked>Correo electrónico</ion-label>
<ion-input [(ngModel)]="userModel.email" type="email" autocorrect="off" autocapitalize="none" name="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$"
required></ion-input>
</ion-item>
<ion-item>
<ion-label stacked>Contraseña</ion-label>
<ion-input [(ngModel)]="userModel.password" type="password" name="password" required minlength="6"></ion-input>
</ion-item>
<div padding-left padding-right padding-top>
<button ion-button [disabled]="!signUpForm.form.valid" block>Registrarse</button>
</div>
</ion-list>
</form>
</ion-content>

view raw

signup2.html

hosted with ❤ by GitHub

En la vista sólo estamos enlazando los campos input al modelo userModel definido en el componente/controlador de la pantalla, configurando el formulario y validaciones como pueden ver en las líneas 8, 12, 18 y 22.

En este punto podemos probar la funcionalidad de registrar usuarios. Una vez que hayamos registrado alguno podemos ir a la consola de Firebase, en la sección de autenticación y veremos al usuario registrado:

Usuarios en Firebase
Usuarios en Firebase

Iniciando sesión

Ahora regresaremos a la pantalla de inicio de sesión en los archivos src/pages/signin/signin.ts y src/pages/signin/signin.html:


import { Component } from '@angular/core';
import { NavController, LoadingController, AlertController } from 'ionic-angular';
import { AuthService } from '../../providers/auth-service';
import { UserModel } from '../../models/user-model';
import { SignUpPage } from '../signup/signup';
import { HomePage } from '../home/home';
@Component({
selector: 'page-signin',
templateUrl: 'signin.html'
})
export class SignInPage {
userModel: UserModel;
constructor(
public navCtrl: NavController,
public loadingCtrl: LoadingController,
public alertCtrl: AlertController,
public authService: AuthService) {
this.userModel = new UserModel();
}
signIn() {
let loading = this.loadingCtrl.create({
content: 'Iniciando sesión. Por favor, espere…'
});
loading.present();
this.authService.signInWithEmailAndPassword(this.userModel).then(result => {
loading.dismiss();
this.navCtrl.setRoot(HomePage);
}).catch(error => {
loading.dismiss();
console.log(error);
this.alert('Error', 'Ha ocurrido un error inesperado. Por favor intente nuevamente.');
});
}
signUp() {
this.navCtrl.push(SignUpPage);
}
alert(title: string, message: string) {
let alert = this.alertCtrl.create({
title: title,
subTitle: message,
buttons: ['OK']
});
alert.present();
}
}

view raw

signin2.ts

hosted with ❤ by GitHub

Leyendo el código podemos ver que es bastante parecido al de signup.ts sólo que en este caso utilizamos el método signInWithEmailAndPassword() del servicio de autenticación para autenticar al usuario, si todo va bien enviamos al usuario a la pantalla de inicio HomePage.


<ion-header>
<ion-navbar hideBackButton="true">
<ion-title>Iniciar Sesión</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<form #signInForm="ngForm" (submit)="signIn()">
<ion-list>
<ion-item>
<ion-label stacked>Correo electrónico</ion-label>
<ion-input [(ngModel)]="userModel.email" type="email" autocorrect="off" autocapitalize="none" name="email" pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$"
required></ion-input>
</ion-item>
<ion-item>
<ion-label stacked>Contraseña</ion-label>
<ion-input [(ngModel)]="userModel.password" type="password" name="password" required minlength="6"></ion-input>
</ion-item>
<div padding-left padding-right padding-top>
<button ion-button [disabled]="!signInForm.form.valid" block>Entrar</button>
</div>
<div padding-left padding-right>
<p>&iquest;No tiene Cuenta de Usuario? <a (click)="signUp()">Regístrese</a>
</div>
</ion-list>
</form>
</ion-content>

view raw

signin2.html

hosted with ❤ by GitHub

Igual que en signup.html realizamos el enlace (binding) con el modelo, configuramos el formulario y sólo activamos el botón “Entrar” si todas las validaciones son válidas.

Y ya podemos empezar a iniciar sesión con los usuarios que hayamos registrado.

Bonus

Entrar directamente si el usuario ya está autenticado

Sólo necesitamos modificar el componente principal de la aplicación MyApp el cual es el punto inicial de la misma y se encuentra en src/app/app.component.ts, realizamos los siguientes cambios:


import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { AuthService } from '../providers/auth-service';
import { SignInPage } from '../pages/signin/signin';
import { HomePage } from '../pages/home/home';
@Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage: any = SignInPage;
constructor(
platform: Platform,
statusBar: StatusBar,
splashScreen: SplashScreen,
authService: AuthService) {
if (authService.authenticated) {
this.rootPage = SignInPage;
} else {
this.rootPage = HomePage;
}
platform.ready().then(() => {
statusBar.styleDefault();
splashScreen.hide();
});
}
}

  • Importamos el servicio de autenticación AuthService en la línea 6.
  • En las siguientes líneas 8 y 9 importamos las pantallas (páginas) de inicio de sesión y de inicio.
  • Inyectamos el servicio de autenticacion en el contructor de la clase en la línea 21.
  • Finalmente en la línea 22 chequeamos la propiedad authenticated (la cual mencionamos anteriormente en este post) si su valor es true entonces el usuario ya está autenticado por lo que establecemos a HomePage como la pantalla inicial de la aplicación a través de la propiedad rootPage, de lo contrario, establecemos a SignInPage como la pantalla inicial.

Cerrar sesión

Para cerrar sesión vamos a modificar la vista de la pantalla de inicio HomePage (src/pages/home/home.html) para colocar un botón de cerrar sesión en la barra de navegación (también aprovechamos e hicimos unos pequeños cambios de texto):


<ion-header>
<ion-navbar>
<ion-title>
IonFire
</ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="signOut()">
<ion-icon name="log-out"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content padding>
<p>
Bienvenido a IonFire.
</p>
</ion-content>

view raw

home.html

hosted with ❤ by GitHub

Al botón le asignamos el método signOut() para ser ejecutado una vez que el mismo sea tocado. Este método lo implementamos en el controlador de la pantalla HomePage que se encuentra en src/pages/home/home.ts:


import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
import { AuthService } from '../../providers/auth-service';
import { SignInPage } from '../signin/signin';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(
public navCtrl: NavController,
public authService: AuthService) {
}
signOut() {
this.authService.signOut();
this.navCtrl.setRoot(SignInPage);
}
}

view raw

home.ts

hosted with ❤ by GitHub

Para cerrar la sesión hicimos uso del método signOut() que ya teníamos implementado en el servicio de autenticación AuthService, por lo que hubo que importarlo e inyectarlo en el constructor de la case como ya hemos hecho en varias ocaciones. La implementación del método signOut() fue muy sencilla pues fue sólo utilizar el método de mismo nombre en el servicio de autenticación y luego cambiarnos a la página SignInPage la cual también fue importada en la línea 6.

Conclusiones

Como pudimos ver, es muy conveniente utilizar servicios como Firebase para que se encarguen de funcionalidades de backend que de lo contrario tendríamos que escribir y mantener nosotros mismos. Por otro lado Firebase nos brinda la confianza de Google Cloud como infraestructura, si nuestra aplicación comienza a tener un volumen grande de usuarios podemos escalar sin problemas.

En otros posts ver cómo utilizar otros métodos de autenticación de Firebase (como Facebook) y otras funcionalidades de Firebase (como la base de datos).

Si te gustó el post ayuda a compartirlo en tus redes sociales 🙂

31 thoughts on “Autenticación con correo y contraseña en Ionic con Firebase – Parte 2

  1. Tengo una duda, para un proyecto que puede escalar a un nivel alto de usuarios, es conveniente usar firebase?

    1. Si, siempre y cuando tengas el presupuesto necesario (como mismo sucede en el caso de AWS y Azure), con el plan gratis tienes algunas cuotas con las que puedes empezar, en dependencia del volumen que vaya teniendo tu proyecto vas a necesitar más capacidad de procesamiento, aquí puedes ver los precios de los distintos planes https://firebase.google.com/pricing/
      Tomado de la página de inicio de Firebase: “Firebase is built on Google infrastructure and scales automatically, for even the largest apps”.

  2. Hola excelente tutorial y te lo agradezco muchisimo ahora solo una duda al querer compilar la app o subirla a ionic view me manda un error en el promise-polyfill.js segun entiendo podrias ayudarme

    1. Hola Ruben, gracias por tu comentario, realmente necesito más detalles para poder tratar de ayudarte, ¿exactamente cuándo te da el error? ¿cuando ejecutas ionic upload? o ¿cuando estás ejecutando ya la aplicación dentro de Ionic View?

    2. Hola Ruben, por si acaso si no has resuelto el error, me acaba de suceder lo mismo tratando de ejecutar la aplicación en el emulador de Android y lo solucioné instalando: npm install promise-polyfill –save-exact

  3. Hola, gracias por el tutorial, espero que pronto agregues más contenido y estoy en la espera de la autenticación con face y google, también me surgió la duda de qué pasa si un usuario no recuerda su contraseña, cómo la podría recuperar o en su caso reestablecer y también cuál es el procedimiento para salir de su sesión (deslogearse).

    soy principiante y te agradezco mucho.

    Saludos!!!

    1. Hola, me alegra que te sea útil el contenido, el API de Firebase te permite implementar cambio de contraseña, resetear contraseña y hasta enviar códigos de confirmación para validar el usuario cuando se registra, poco a poco voy a ir publicando sobre esos temas al igual que autenticación con Facebook. Saludos.

    1. Hola Anibal, acabo de acualizar este post adicionando una sección llamada “Bonus” en la cual explico cómo hacer lo que me pides y además cómo cerrar sesión. Saludos.

  4. hola geyKey excelente tutorial , muy bien explicado, quisiera ver si me puieras ayudar con este error :
    [WARN] Error occurred during command execution from a CLI plugin
    (@ionic/cli-plugin-cordova). Your plugins may be out of date.
    Error: ./node_modules/firebase/utils/promise.js
    Module not found: Error: Can’t resolve ‘promise-polyfill’ in ‘C:\xampp\htdocs\ionicFire\no de_modules\firebase\utils’
    resolve ‘promise-polyfill’ in ‘C:\xampp\htdocs\ionicFire\node_modules\firebase\utils’
    Parsed request is a module
    using description file: C:\xampp\htdocs\ionicFire\node_modules\firebase\package.json (re lative path: ./utils)
    Field ‘browser’ doesn’t contain a valid alias configuration

    ya instale la ultima version pero aun asi no me permite correrlo en mi telefono android, si pudieras ayudarme te lo agradeceria, saludos

    1. Hola Eduard, gracias por tu comentario, yo tuve un error similar ejecutando la app en el emulador de Android y lo solucioné instalando: npm install promise-polyfill –save-exact
      Pruébalo y dime cómo te va. Saludos.

  5. me fue muy bien muchisimas gracias, ahora que termine la app y quiero pasarlo a mi telefono me marca un error en el formulario signIn.html y signUp.html , lo que pasa es que me pide que el el form cree algo como : [FormGroup]=”myForm” donde myForm comunmente es quien contiene la validacion y los datos , nose como lo manejes tu con #signInForm=”ngModel”, agradecería si pudieras ayudarme en esta duda.

  6. este es el link del archivo de registro : https://gist.github.com/anonymous/b905fb7ca8864e2763cdb336dfd42676

    lo que quiero saber es cual es la diferencia de usar [FormGroup]=”myForm” en el archivo .html y el que tu tienes
    que es :#signInForm=”ngForm”, ya lo hice como tu y me funciona perfectamente , pero estoy creando una aplicacion de un proyecto y veo que cuando pasan mas de dos objetos es decir email, nombre, password,apellido usan un objeto myfor de tipo FormGroup cuando se envia la informacion o se ejecuta el formulario, soy principiante como puedes ver no tengo mucho tiempo en esto por eso las dudas , lo que quiero agregar mas datos al formulario signUp.html aparte de correo y password como nombre y apellido para que se registre usando el mismo procedimiento de aqui y que se guarden en la base de datos fireBase pero nose como hacerle y agradeceria que pudieras ayudarme.

    a esto me refiero que quiero masomenos tratar de hace signIn.ts

    export class SigninPage {

    userModel : UserModel;
    myForm :FormGroup;
    constructor(public navCtrl: NavController,
    public navParams: NavParams,
    public loadingCtrl : LoadingController,
    public alertCtrl : AlertController,
    public authService : AuthService,
    public formBuildier: FormBuilder
    ) {

    this.userModel =new UserModel();
    this.myForm = formBuilder.group({
    email :[‘ ‘,Validators.required],
    password :[‘ ‘,Validators.required],
    apellido : [‘ ‘, Validators.required]

    })

    }

  7. Ok ya veo te problema, mira lo que pasa es que son dos maneras distintas de implementar formularios en Angular, o lo haces como yo hice que es utilizando ngForms (para formularios sencillos como el mío) o con FormBuilder que es como quieres hacerlo tu ahora, en este caso lo que te pasa es que a la vista (html) le faltan cosas, una de las cosas que te falta, por ejemplo, es que cuando utilizas FormBuilder a tus inputs no le pueden faltar el atributo formControlName con el nombre de la propiedad que utilizaste cuando construiste el formulario por ejemplo “apellido”, “email” o “password”, entre otras cosas…
    Mira hice un versión de mi “signin” utilizando FormBuilder (adicionando además otro campo “firstName”) para que puedas comparar mejor una con otra y veas las diferencias:


    <ion-header>
    <ion-navbar hideBackButton="true">
    <ion-title>Iniciar Sesión</ion-title>
    </ion-navbar>
    </ion-header>
    <ion-content>
    <form [formGroup]="signInForm">
    <ion-list>
    <ion-item>
    <ion-label stacked>Correo electrónico</ion-label>
    <ion-input type="email" formControlName="email" autocorrect="off" autocapitalize="none"></ion-input>
    </ion-item>
    <ion-item>
    <ion-label stacked>Contraseña</ion-label>
    <ion-input type="password" formControlName="password"></ion-input>
    </ion-item>
    <ion-item>
    <ion-label stacked>Nombre</ion-label>
    <ion-input type="text" formControlName="firstName" autocorrect="off"></ion-input>
    </ion-item>
    <div padding-left padding-right padding-top>
    <button ion-button [disabled]="!signInForm.valid" (click)="signIn()" block>Entrar</button>
    </div>
    </ion-list>
    </form>
    </ion-content>


    import { Component } from '@angular/core';
    import { NavController, LoadingController, AlertController } from 'ionic-angular';
    import { Validators, FormBuilder, FormGroup } from '@angular/forms';
    import { AuthService } from '../../providers/auth-service';
    import { UserModel } from '../../models/user-model';
    import { SignUpPage } from '../signup/signup';
    import { HomePage } from '../home/home';
    @Component({
    selector: 'page-signin',
    templateUrl: 'signin.html'
    })
    export class SignInPage {
    private signInForm: FormGroup;
    constructor(
    public navCtrl: NavController,
    public loadingCtrl: LoadingController,
    public alertCtrl: AlertController,
    public authService: AuthService,
    private formBuilder: FormBuilder) {
    this.signInForm = this.formBuilder.group({
    email: ['', Validators.compose([Validators.required, Validators.pattern('[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,3}$')])],
    password: ['', Validators.compose([Validators.required, Validators.minLength(6)])],
    firstName: ['', Validators.required]
    });
    }
    signIn() {
    let loading = this.loadingCtrl.create({
    content: 'Iniciando sesión. Por favor, espere…'
    });
    loading.present();
    let userModel = new UserModel();
    userModel.email = this.signInForm.value.email;
    userModel.password = this.signInForm.value.email;
    userModel.firtName = this.signInForm.value.firtName;
    this.authService.signInWithEmailAndPassword(userModel).then(result => {
    loading.dismiss();
    this.navCtrl.setRoot(HomePage);
    }).catch(error => {
    loading.dismiss();
    console.log(error);
    this.alert('Error', 'Ha ocurrido un error inesperado. Por favor intente nuevamente.');
    });
    }
    signUp() {
    this.navCtrl.push(SignUpPage);
    }
    alert(title: string, message: string) {
    let alert = this.alertCtrl.create({
    title: title,
    subTitle: message,
    buttons: ['OK']
    });
    alert.present();
    }
    }


    export class UserModel {
    email: string;
    password: string;
    firtName: string;
    }

    Mira en este post (en inglés) puedes ver 3 ejemplos distintos sobre cómo hacer formularios con sus ventanjas y desventajas:

    https://ionicframework.com/docs/developer-resources/forms/

  8. Muchas Gracias amigo , ahora veo las diferencias , gracias por compartir tu tiempo y su conocimiento , ya lo probe y tube que agregar un objeto en el archivo signUp.ts puesto que no me dejaria usar let userMode=UserModel si no lo tengo declarado, ahora no me marca error ni nada solo que al correr el programa se pone la pantalla en blanco y ahi se queda, creo que se me ha deber escapado algo que al correr el signIn.html lo lo reconoce, Gracias.

  9. este es el codigo que use : https://gist.github.com/anonymous/9247a87dad642be2614ce9c593c0be9d
    esta signUp.ts , .html , app.component.ts, module.ts , user-model.ts ,auth-service pero aun asi me sigue apareciendo la pantalla de mi telefono y el servidor de ionic en blanco , agradeceria si me podrias asesorar por que pasa esto. investigue esto y se dice que es por que paso de tiempo que necesitaba, cuando use el otro formulario si me funciono, pero ahora tube este problema

  10. Amigo Geykel perdon por andar enfadando tanto esque aun me surgen dudas jajaja, ya por fin pude auntenticar con mas de 2 datos pero mi duda ahora es ¿Donde queda la demas informacion y donde la puedo ver en mi proyecto firebase? no me manda ningun error ni nada ya hice pruebas y funciona pero nose donde queda la demas informacion en el caso de que demas usuarios usuarian la aplicacion y yo como administrador quiera verla.

    1. Hola Eduard, el problema es que en el proveedor “authService” estós utilizando métodos del API de autenticación de Firebase, por ejemplo para crear el usuario utilizas “createUserWithEmailAndPassword” del objeto “auth” el cual recibe el “username” y el “password” y te crea el usuario con esos datos, el usuario en Firebase “sólo” tiene esos datos, si deseas poner otros datos (como nombres y apellidos) tienes que preparar un lugar para guardarlos y relacionarlos al usuario, por ejemplo puedes utilizar el servicio de base de datos de Firebase, ahi puedes crear una colección que se llame “users” y con el “uid” del usuario que recien creaste puedes crear una entrada en esa colección con los demás campos que quieras. El próximo post que voy a escribir está medio relacionado con esto, pero no he tenido mucho tiempo en estos días. Saludos.

  11. Hola amigo, muchas gracias por tu post… estarás nombrado en el resultado de mi tesis jajajajaj… compañero tengo una tremenda duda, como puedo hacer que el usuario se mantenga logueado la próxima vez que inicie sesión?

    1. Hola Gonzalo, muchas gracias, si te fijas en este mismo post verás que hay una sección casi al final que se llama “Bonus” donde tienes lo que andas buscando y además cerrar sesión.

  12. Muy bien amigo geykel pues muchas gracias por todo y si estare pendiente a los siguientes posts muy interesantes e utiles, saludos.

  13. Hola Geykel, quiero poner el mail del usuario en otra vista por ejemplo en home en el html ¿como hago para tomar el dato?

    1. Hola Ezequiel, en la vista donde quieras mostrar el email puedes utilizar (inyectar) el proveedor AuthService y utilizar la propiedad “authenticated” para verificar si el usuario está autenticado o no, si está autenticado entonces puedes utilizar la propiedad user la cual a su vez tiene una propiedad email. Espero te ayude, saludos.

  14. Hola Geykel, otra pregunta, quiero poner el botón de volver como esta en la vista signup en home por ejemplo, ¿como hago? porque busque en el código y no lo veo

  15. Hola, que buen post, tengo el siguiente error:

    ——————————
    Typescript Error
    Cannot find module ‘firebase/app’.
    —————————–

    es cuando das esa ruta en la línea 4 del archivo “auth-service.ts”, estas complemanete seguro que esa es la ruta? debo hacer algo adicional?

    gracias!!

    1. Hola Camilo, lamentablemente este artículo fue escrito hace más de 1 año por lo que es muy probable que el API de Firebase haya cambiando desde entonces, tienes que ver cuál versión te está instalando npm y ver qué cambios debes hacer basado en la versión que tienes. Saludos.

  16. Otro error es el siguiente:

    Typescript Error
    Module ‘”/node_modules/firebase/index”‘ has no exported member ‘Promise’.

    gracias

Leave a reply to geykel Cancel reply