Construye una App con Ionic y Firebase paso a paso
Con Autenticación, Base de datos y almacenamiento de imágenes usando Firebase
Introducción
En este tutorial vamos a aprender a hacer un CRUD (Create, Read, Update, Delete) utilizando Cloud Firestore como base de datos y Cloud Storage como almacenamiento de imágenes.
En IonicThemes somos grandes creyentes de que aprender a programar es mucho más fácil si tenemos un ejemplo práctico. Es por eso que en todos nuestros tutoriales siempre creamos una aplicación de ejemplo totalmente funcional y gratuita.
En el tutorial original (en inglés) que está posteado en IonicThemes, te puedes descargar gratis la app de ionic y firebase que hemos realizado para éste tutorial. Esta app incluye un login básico utilizando Firebase (email/password) y una lista de tareas sobre la cual vamos a realizar las operaciones de CRUD, crear, listar, editar y borrar una tarea.
Cada tarea contará con los siguientes atributos:
- Título
- Descripción
- Imagen (que se almacenará en firebase storage)
Es importante destacar que las tareas van a estar asociadas al usuario logueado. Para aprender más detalladamente sobre la autenticación con firebase visita este tutorial.
Crear la aplicación de Ionic Framework
Para comenzar con este ejemplo vamos a crear una aplicación con Ionic Framework. Puedes descargarte gratuitamente éste ejemplo o puedes crear tu propia app de cero.
Esta es la aplicación que vamos a construir en éste tutorial de Ionic + Firebase:
Para comunicar nuestra aplicación de ionic con el proyecto de firebase vamos a utilizar el plugin de angularfire2. Te mostraré cómo crear el proyecto de Firebase en el siguiente paso.
Para instalar AngularFire debemos correr el siguiente comando desde nuestra consola:
npm install firebase angularfire2 --save
También tenemos que instalar en nuestra aplicación de Ionic, el plugin de Image Picker. Vamos a utilizar este plugin para que nuestra app de Ionic pueda acceder a la galería de imágenes de nuestro celular y así poder crear tareas con imágenes que luego guardaremos en el Firebase Storage.
Para instalar Image picker plugin, corremos los siguientes comandos en nuestra consola:
ionic cordova plugin add cordova-plugin-telerik-imagepicker --variable PHOTO_LIBRARY_USAGE_DESCRIPTION="your usage message"npm install --save @ionic-native/image-picker
Si quieres aprender más sobre el manejo de imágenes en Firebase te recomiendo leer How to upload an image to Firebase from an Ionic app? y si quieres aprender sobre manejo de imágenes en general dentro de una aplicación de Ionic Framework te sugiero leer Image handling in an Ionic 3 app.
Crear la Aplicación de Firebase
Una vez instalado AngularFire (el plugin que vamos a utilizar para comunicar nuestra Ionic app con Firebase), debemos crear un nuevo proyecto en Firebase. Para crear tu proyecto, dirígete a la consola de firebase, donde verás el siguiente menú:
Debes hacer click en “Add Firebase to your web app” para ver las credenciales de tu nueva aplicación de Firebase. Estas credenciales las vamos a precisar para indicarle a nuestra aplicación de Ionic que se comunique con nuestra aplicación de Firebase.
El próximo paso es agregar nuestras credenciales de Firebase en nuestra aplicación de Ionic Framework. Para esto iremos a nuestro proyecto de Ionic que creamos en el paso anterior y agregaremos el siguiente código en el archivo environment.ts ubicado en src/environments/:
export const environment = {
production: false,
firebase: {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
databaseURL: "YOUR_DATABASE_URL",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET",
messagingSenderId: "YOUR_SENDER_ID"
}
};
Por favor, ten en cuenta que tienes que reemplazar las constantes anteriores con tus propios valores.
En este momento estamos prontos para comenzar con la implementación del CRUD con Firebase y Ionic.
Quiero invitarte a suscribirte a nuestra newsletter para recibir noticias de Ionic Framework así como ofertas de los templates que ofrecemos en IonicThemes.
CRUD con Ionic y Firebase
Para implementar de la mejor manera las funcionalidades de CRUD vamos a crear dos servicios, uno en donde tendremos todo lo relacionado con la autenticación auth.service.ts y el otro lo relacionado con la lógica del CRUD firebase.service.ts.
Autenticación con Firebase
Comenzaremos con los métodos del servicio de autenticación, en donde tendremos el login, register y logout. Optamos implementar una autenticación simple con el único objetivo de que cada usuario tenga sus propias tareas. En otras palabras, cada tarea sólo pertenece al usuario que la creó.
import { Injectable } from "@angular/core";
import 'rxjs/add/operator/toPromise';
import * as firebase from 'firebase/app';
import { FirebaseService } from './firebase.service';@Injectable()export class AuthService { constructor(
private firebaseService: FirebaseService
){} doRegister(value){
return new Promise<any>((resolve, reject) => {
firebase.auth().createUserWithEmailAndPassword(value.email,
value.password)
.then(
res => resolve(res),
err => reject(err))
})
} doLogin(value){
return new Promise<any>((resolve, reject) => {
firebase.auth().signInWithEmailAndPassword(value.email,
value.password)
.then(
res => resolve(res),
err => reject(err))
})
} doLogout(){
return new Promise((resolve, reject) => {
if(firebase.auth().currentUser){
firebase.auth().signOut()
.then(() => {
this.firebaseService.unsubscribeOnLogOut();
resolve();
}).catch((error) => {
reject();
});
}
})
}
}
Si quieres implementar una autenticación más completa con Firebase y Ionic te recomiendo leer Firebase Authentication in Ionic Framework Apps donde explicamos cómo crear una aplicación de Ionic Framework que ofrezca autenticación tanto con proveedores sociales como (facebook, google y twitter) así como también con email y contraseña.
Firebase CRUD con Ionic Framework
Empecemos a ver cómo implementar las distintas funciones del CRUD en nuestra Ionic App usando Firebase.
CREAR TAREA
Comenzaremos con la funcionalidad de crear una tarea, por lo que vamos a implementar un método createTask() en el servicio firebase.service.ts.
createTask(value){
return new Promise<any>((resolve, reject) => {
let currentUser = firebase.auth().currentUser;
this.afs.collection('people').doc(currentUser.uid)
.collection('task').add({
title: value.title,
description: value.description,
image: value.image
})
.then(
res => resolve(res),
err => reject(err)
)
})
}
Tal como mencionamos anteriormente, las tareas van a estar asignadas al usuario logueado, por lo que utilizamos el método firebase.auth().currentUser para obtener su uid.
IMPORTANTE: Notar que el value.image debe ser la url de descarga que ya te vamos a explicar cómo obtener.
Como podemos observar, cada tarea tiene una imagen que se selecciona de la galería de imágenes del celular, utilizando el plugin de Image Picker y es guardada en el Cloud Storage.
Cómo logramos esto? Muy simple, hay que seguir estos 3 pasos:
- Definir la referencia de dónde vamos a guardar la imagen dentro del storage:
let storageRef = firebase.storage().ref();
let imageRef = storageRef.child('image').child('imageName');
2. Luego debemos convertir la URI que nos devuelve el plugin de ImagePicker una url en base64. Para esto vamos a usar un canvas.
encodeImageUri(imageUri, callback) {
var c = document.createElement('canvas');
var ctx = c.getContext("2d");
var img = new Image();
img.onload = function () {
var aux:any = this;
c.width = aux.width;
c.height = aux.height;
ctx.drawImage(img, 0, 0);
var dataURL = c.toDataURL("image/jpeg");
callback(dataURL);
};
img.src = imageUri;
};
3. Y como paso final utilizamos el método de firebase putString(image64, ‘data_url’) cuya respuesta devuelve la url que se le asignó a la imagen subida al firebase storage. Podemos acceder a esa url haciendo snapshot.ref.getDownloadURL(). Entonces el método final sería el siguiente:
uploadImage(imageURI, randomId){
return new Promise<any>((resolve, reject) => {
let storageRef = firebase.storage().ref();
let imageRef = storageRef.child('image').child(randomId);
this.encodeImageUri(imageURI, function(image64){
imageRef.putString(image64, 'data_url')
.then(snapshot => {
snapshot.ref.getDownloadURL()
.then(res => resolve(res))
}, err => {
reject(err);
})
})
})
}
LISTAR TAREAS
Una vez creada una o más tareas, vamos a poder ver la lista de las mismas. Para obtener todas las tareas de un usuario implementamos un método getTasks() en el servicio.
getTasks(){
return new Promise<any>((resolve, reject) => {
let currentUser = firebase.auth().currentUser;
this.snapshotChangesSubscription =
this.afs.collection('people').doc(currentUser.uid)
.collection('task').snapshotChanges()
.subscribe(snapshots => {
resolve(snapshots);
})
});
}
Es muy importante utilizar el método snapshotChanges() ya que en la respuesta nos retorna el id de cada Tarea, el cual se va a utilizar a la hora de realizar el update y delete.
El otro método de obtención de datos de una collection es valueChanges() el cual nos retorna un json con los atributos de dicha Tarea, pero sin su id. Para más información sobre estas dos opciones visita este link.
MODIFICAR TAREAS
Pasamos ahora al método updateTask() del servicio el cual recibe como parámetro la id de la Tarea a editar (como mencionamos arriba) y el nuevo valor de la misma.
updateTask(taskKey, value){
return new Promise<any>((resolve, reject) => {
let currentUser = firebase.auth().currentUser;
this.afs.collection('people').doc(currentUser.uid)
.collection('task').doc(taskKey).set(value)
.then(
res => resolve(res),
err => reject(err)
)
})
}
Es importante saber que si se quiere modificar uno o dos de los atributos de una Tarea, el nuevo valor debe mantener el valor anterior, es decir, que si se quiere realizar un update del atributo image de la Tarea X, el parámetro value debe contener su descripción y título actual.
ELIMINAR TAREA
Para borrar una Tarea, es muy sencillo, solo debemos conocer el id de la Tarea a eliminar.
deleteTask(taskKey){
return new Promise<any>((resolve, reject) => {
let currentUser = firebase.auth().currentUser;
this.afs.collection('people').doc(currentUser.uid)
.collection('task').doc(taskKey).delete()
.then(
res => resolve(res),
err => reject(err)
)
})
}
Conclusiones sobre éste tutorial de Ionic y Firebase
En este tutorial de Firebase y Ionic aprendimos como realizar un CRUD simple utilizando Cloud Firestore en una aplicación de Ionic 3 para listar, crear, editar y eliminar objetos de una colección, en nuestro caso: Tareas.
Además vimos los diferentes caminos para la obtención de datos en una collection de firebase: valueChanges() y snapshotChanges().
Como bonus no solo guardamos una imagen en el Cloud Storage, sino que también enseñamos cómo obtener su url de descarga para así guardarla en la base de datos.
Espero que este tutorial de cómo crear un CRUD con Firebase y Ionic Framework te haya sido útil y recuerda que si tienes cualquier duda o sugerencia puedes dejarnos un comentario aquí abajo.
En IonicThemes creamos continuamente tutoriales para que puedas aprender a crear las mejores aplicaciones móviles usando Ionic Framework.
Si quieres aprender más sobre Firebase y Ionic visita este link para ver todos los tutoriales y ejemplos de código gratuitos que hemos construido con Firebase para ayudar a la comunidad de Ionic.
También quiero aprovechar para contarte que en IonicThemes hemos creado el template más completo y hermoso con Ionic Framework que puedas alguna vez desear. Tiene muchísimas funcionalidades, integraciones y componentes que seguro van a hacer que tu aplicación hecha con Ionic Framework se destaque del resto.
Observa el video y prueba la demo en vivo.