En esta entrada, vamos a ver como hacer un CRUD con Vue.js, Tailwind CSS para los estilos y Firebase como base de datos.
Según Wikipedia, Firebase es una plataforma para el desarrollo de aplicaciones web y aplicaciones móviles de Google. Firebase tiene varios servicios, pero el que vamos a utilizar hoy es Realtime Database, tal como dice su nombre, es un servicio de bases de datos en tiempo real. Vincularemos esta base de datos con Vue.js y crearemos un CRUD en el que se sincronicen los datos en tiempo real. Empezamos!
Preparación
Primero de todo, instalamos vue-cli, que nos proporciona una UI por terminal o web para crear proyectos Vue a partir de indicar los paquetes que queremos. Para instalarlo, ejecutamos el siguiente comando:
1 |
npm install -g @vue/cli |
Una vez finalice el proceso de instalación, vamos a crear el proyecto. Para ello vamos a ejecutar el siguiente comando:
1 |
vue create vue-crud-firebase |
Se te abrirá en la terminal la UI que hablaba antes. Yo elegí las siguientes opciones para hacer este post:
Hemos indicado que instale vue-router que es una librería que ya tratamos anteriormente, puedes echarle un vistazo a los posts.
Cuando acabe este proceso tendremos el proyecto creado y ya podremos empezar! Entramos al directorio creado y arrancamos el servidor de desarrollo para ver que todo funcione correctamente:
1 2 |
cd vue-crud-firebase npm run serve |
Ya tenemos la estructura básica del proyecto y vemos que arranca correctamente. Ahora, vamos a instalar unos paquetes extra que vamos a necesitar. Instalaremos el paquete Firebase y VueFire (para conectar nuestra app con Firebase) y Tailwind CSS. Para ello, desde el directorio del proyecto ejecutamos lo siguiente:
1 |
npm i firebase vuefire tailwindcss --save |
Configurar Tailwind CSS con Vue
Antes de continuar, vamos a configurar Tailwind CSS para poderlo utilizar en los componentes Vue. Si quieres saber más sobre Tailwind CSS, echa un vistazo a este post.
Generamos el archivo de configuración:
1 |
./node_modules/.bin/tailwind init tailwind-config.js |
Con este comando, se nos generará un archivo tailwind-config.js en la raíz de nuestro proyecto.
Creamos un archivo CSS en src/assets llamado styles.css y ponemos el código de este enlace dentro.
Después, en el archivo postcss.config.js ponemos este código:
1 2 3 4 5 6 |
module.exports = { "plugins": [ require('tailwindcss')('./tailwind-config.js'), require('autoprefixer')(), ] } |
Para acabar, tendremos que importar los estilos en el archivo main.js :
1 |
import '@/assets/styles.css' |
Cuando tengamos todo esto ya tendremos Tailwind CSS configurado para poderlo utilizar con Vue.js.
Este apartado está basado en este artículo.
Firebase
Ya tenemos la base del proyecto con todo instalado. Ahora vamos a crear una cuenta en Firebase. Para crear una cuenta en Firebase, simplemente tenéis que ir a “Acceder” (arriba a la derecha), entrar con una cuenta de Google y ya estaríamos dentro.
Tenemos que crear un proyecto. Para ello vamos a “Acceder a la consola” y nos saldrá esto:
Le damos en “Añadir proyecto” y se nos abrirá un popup. Indicamos la información que nos piden y le damos a “Crear proyecto”. Cuando acabe, vamos a “Database” y creamos nuestra realtime database:
Le damos a “Crear base de datos” y se nos abrirá un popup. En este popup, seleccionamos “Empezar con el modo prueba” para permitir de manera rápida todas las operaciones de escritura y lectura.
Vincular Vue con Firebase
Para vincular Vue con la base de datos de Firebase creada en el paso anterior, vamos a crear un archivo llamado firebase.js en src/ con lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import firebase from 'firebase' const config = { apiKey: "XXX", authDomain: "XXX", databaseURL: "XXX", projectId: "XXX", storageBucket: "XXX", messagingSenderId: "XXX" }; firebase.initializeApp(config); export const db = firebase.database(); |
Los datos marcados con XXX los sacamos del panel de control de Firebase. Tenemos que ir “Project overview” y después hacer click en el icono de la plataforma donde lo vamos a integrar. En nuestro caso, sería el último, que es JS:
Se nos abrirá un popup con toda la información para sustituir en el archivo firebase.js .
También tenemos que añadir las siguientes líneas al archivo main.js :
1 2 3 |
const VueFire = require('vuefire') Vue.use(VueFire) |
Le indicamos a Vue que incluya la librería VueFire que usaremos para obtener los datos de Firebase de manera súper sencilla. Puedes ver su documentación aquí.
Si todo ha salido bien, ya debería estar vinculado nuestro proyecto con la base de datos en Firebase:
Como puedes ver en el GIF anterior, he creado a mano en Firebase un objeto y automáticamente se muestra en mi local. Esto es un ejemplo rápido que he hecho para ver si estaba sincronizado todo.
Ahora que ya tenemos todo, vamos a ver como hacer un CRUD de usuarios (name, lastname, age) sencillo paso a paso con Vue.js y Firebase.
Crear
Lo primero de vamos a hacer será el crear (la C de CRUD). Yo, antes de empezar, he hecho un poco de limpieza del proyecto que hemos generado en uno de los pasos anteriores. He borrado componentes (HelloWorld) y rutas que no voy a utilizar (about).
Vamos a crear el formulario que añada la información a la base de datos. Lo que voy a hacer es, aprovechar la view Home.vue para poner el formulario de crear en la parte superior y por debajo el listado (siguiente punto). Entonces, abrimos el fichero Home.vue y añadimos el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
<template> <div> <form v-on:submit.prevent="onSubmit"> <div class="mb-4"> <label class="block text-grey-darkest text-sm font-bold mb-2" for="name">Name</label> <input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight focus:outline-none focus:shadow-outline" id="name" type="text" placeholder="Name" v-model="user.name"> </div> <div class="mb-4"> <label class="block text-grey-darkest text-sm font-bold mb-2" for="lastname">Lastname</label> <input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight focus:outline-none focus:shadow-outline" id="lastname" type="text" placeholder="Lastname" v-model="user.lastname"> </div> <div class="mb-4"> <label class="block text-grey-darkest text-sm font-bold mb-2" for="lastname">Age</label> <input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight focus:outline-none focus:shadow-outline" id="lastname" type="text" placeholder="Age" v-model="user.age"> </div> <div class="text-center"> <button type="submit" class="bg-blue hover:bg-blue-dark text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">Add</button> </div> </form> </div> </template> <script> import {db} from '../firebase'; export default { data() { return { users: {}, user: { name: '', lastname: '', age: '', } } }, firebase: { users: db.ref('users') }, methods: { onSubmit() { this.$firebaseRefs.users.push(this.user) this.user = { name: '', lastname: '', age: '' } } } } </script> |
Estamos creando un formulario con unos inputs y un botón al cual le estamos dando estilo con Tailwind CSS. Le añadimos un evento al formulario ( v-on:submit.prevent ) para que cuando se haga submit se ejecute la función onSubmit . Lo que hace esta función, es obtener los datos del formulario a través de this.user (propiedad añadida al data ), sincroniza estos datos con Firebase gracias a VueFire y finalmente limipiamos el formulario.
Listar
Lo siguiente que vamos a hacer va a ser el listado (la R de CRUD). Como he dicho anteriormente, vamos a utilizar la view Home.vue tanto para el formulario de crear como para el listado. Por tanto, añadimos este código en Home.vue después del </form> añadido en el paso anterior:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
... </form> <table class="mt-5"> <thead> <tr class="border-solid border-b"> <th>ID</th> <th>Name</th> <th>Lastname</th> <th>Age</th> <th>Actions</th> </tr> </thead> <tbody> <tr v-for="user in users" v-bind:key="user['.key']"> <td class="px-3">{{user['.key']}}</td> <td class="px-3">{{user.name}}</td> <td class="px-3">{{user.lastname}}</td> <td class="px-3">{{user.age}}</td> <td class="px-3"> # </td> </tr> </tbody> </table> ... |
Y ya está, no tenemos que añadir nada más. Porque en el paso anterior, ya hemos añadido la referencia al objeto de Firebase ( users: db.ref('users') ). Accedemos a la propiedad users que tiene los datos de Firebase, hacemos un bucle ( v-for ) y lo mostramos.
Editar
Ahora vamos con el editar (la U de CRUD). Primero de todo, vamos a crear una view llamada Edit.vue :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<template> <div> <form v-on:submit.prevent="onSubmit"> <div class="mb-4"> <label class="block text-grey-darkest text-sm font-bold mb-2" for="name">Name</label> <input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight focus:outline-none focus:shadow-outline" id="name" type="text" placeholder="Name" v-model="user.name"> </div> <div class="mb-4"> <label class="block text-grey-darkest text-sm font-bold mb-2" for="lastname">Lastname</label> <input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight focus:outline-none focus:shadow-outline" id="lastname" type="text" placeholder="Lastname" v-model="user.lastname"> </div> <div class="mb-4"> <label class="block text-grey-darkest text-sm font-bold mb-2" for="lastname">Age</label> <input class="shadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight focus:outline-none focus:shadow-outline" id="lastname" type="text" placeholder="Age" v-model="user.age"> </div> <div class="text-center"> <button type="submit" class="bg-blue hover:bg-blue-dark text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">Edit</button> </div> </form> </div> </template> <script> import {db} from '../firebase'; export default { data() { return { users: {}, user: { name: '', lastname: '', age: '', } } }, firebase: { users: { source: db.ref('users'), asObject: true } }, created() { let user = this.users[this.$route.params.id] this.user = { name: user.name, lastname: user.lastname, age: user.age, } }, methods: { onSubmit() { this.$firebaseRefs.users.child(this.$route.params.id).set(this.user) this.$router.push({ name: 'home' }) } } } </script> |
Si te fijas, es casi el mismo formulario de crear, simplemente cambian un par de cosas en cuanto a maquetación. Lo interesante es el funcionamiento. Primero de todo, tenemos un evento created que es un hook de Vue.js que se ejecuta cuando cuando la instancia y los eventos, las computed properties, el data y los métodos están creados. Por tanto, en este caso, cuando está todo creado, según el parámetro id de la URL, carga los datos del usuario en la propiedad user .
Después, en el evento submit ( v-on:submit.prevent ) del formulario, se ejecuta la función onSubmit que lo que hace es sincronizar los datos con Firebase y después redirecciona a la home.
Ya tenemos la vista, pero no tenemos la ruta que la llama. Vamos a crearla! En el archivo router.js añadimos esto:
1 2 3 4 5 6 7 8 9 10 |
... import Edit from './views/Edit.vue' ... { path: '/:id', name: 'edit', component: Edit } ... |
Y por último, nos falta crear el enlace que lleve a esta ruta. Vamos a la vista Home.vue y añadimos lo siguiente en la última columna de la tabla:
1 2 3 |
<td> <router-link :to="{ name:'edit', params: { id:user['.key'] } }" class="bg-blue hover:bg-blue-dark text-white font-bold py-2 px-4 rounded normal-case text-xs">Edit</router-link> </td> |
Eliminar
Para acabar el post, vamos a hacer la D de CRUD, que es eliminar. Para ello, vamos a ir a la view Home.vue y vamos a añadir el siguitente código en methods :
1 2 3 4 5 6 |
methods: { … deleteUser(user) { this.$firebaseRefs.users.child(user['.key']).remove() } … |
Este código lo que hace es eliminar el usuario según su propiedad .key que es el identificador de Firebase. El objeto usuario se pasa a través del evento click del botón de eliminar, que vamos a añadir al lado del enlace de editar:
1 2 3 |
<button class="ml-3 bg-red hover:bg-red-dark text-white font-bold py-2 px-4 rounded text-xs" v-on:click="deleteUser(user)"> Delete </button> |
una consulta que código hay que colocar en el archivo style.css dice coloca el código de la siguiente pagina pero no se que codigo colocar, espero tu respuesta muchas gracias por este aporte
Muchas gracias por tu comentario Francisco! El enlace ha cambiado por eso no te salía bien. El nuevo enlace es este (https://tailwindcss.com/docs/installation/#2-add-tailwind-to-your-css), ya está actualizado en el post. Es la sección «Add Tailwind to your CSS».
ya logre correr el proyecto, tuve un error con el src/router.js la configuracion la agregue al archivo /src/router/index.js, en la pagina de la aplicacion no me funciona el listar teniendo datos en firebase, el boton de add no aparece, cuando le doy click en about aparece parte del dialogo de add pero sin boton.
el proyecto lo subi https://github.com/iara84/vue-crud-firebase, por favor me podria revisar el codigo para saber la razon de que el proyecto no funcione correctamente
Hola! La consola te muestra algún error?
Hola,una pregunta; si quiero imprimir un dato en específico de la base de datos, ¿qué debo hacer?
Hola, no acabo de entender a qué te refieres. En la sección «Listar» puedes ver cómo se muestran los datos.