Tablas dinámicas con Vue.js
Hola nuevamente con tod@s, después de un tiempo vengo a iniciar el tema de front-end dentro del blog. En esta ocasión haremos un post acerca del uso de un framework de javascript como es Vue.js. Vamos a introducirnos en el uso del framework, vamos a crear y manipular una tabla dinámicamente y para finalizar vamos a utilizar una persistencia en LocalStorage del navegador para guardar datos dentro del cliente. ¡Empecemos!
Comenzamos por definir un código html base donde podemos distinguir dos cosas:
- Usaremos bootstrap importando únicamente el css para el uso de estilos acorde a su página oficial.
- Vamos a usar Vue.js por medio del CDN para versión de desarrollo de su página oficial antes de la llamada a nuestro propio archivo javascript que denominaremos main.js.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CRUD on Vue.js</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div id="app" class="container">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
De la misma manera, vamos a definir una estructura base de javascript en el archivo main.js para el uso de Vue, donde podemos distinguir las siguientes características:
- En una constante llamada app instanciaremos a Vue.js.
- Dentro de la Instancia de Vue llamaremos al elemento de html que vamos a controlar, en este caso el elemento cuyo id sea 'app'.
- Definimos un objeto dentro de la instancia Vue con el nombre data, y en cuyo interior iniciaremos además un dato llamado 'titulo' con un string.
- Definimos dentro de la instancia de Vue un objeto llamado 'methods' que por el momento dejaremos en blanco.
const app = new Vue({ el: "#app", data: { titulo: 'CRUD de productos con Vue.js' }, methods: { } });
Ahora, dentro de data de la instancia de Vue, vamos a crear los siguientes objetos adicionales:
columnas: ['No.','Descripción','Cantidad','Estado', 'Acciones'], productos: [], nombreNuevoProducto: '', cantidadNuevoProducto: 0
En donde usaremos estos elementos de la siguiente forma:
- Columnas: este objeto guardará el nombre de las columnas para ser usados en la cabecera de la tabla.
- Productos: Es una colecccion de objetos que albergará a los productos de la tabla.
- nombreNuevoProducto: esta variable será atada a un input que albergará el nombre de un nuevo producto.
- cantidadNuevoProducto: esta variable será atada a un input que albergará la cantidad de un nuevo producto.
De la misma manera dentro del objeto methods, crearemos los siguientes metodos que nos van a servir para el efecto:
agregarProducto(){
if(this.nombreNuevoProducto != ''){
this.productos.push({
nombre: this.nombreNuevoProducto,
cantidad: this.cantidadNuevoProducto,
editar: false
});
localStorage.setItem('productos-local', JSON.stringify(this.productos));
this.nombreNuevoProducto = '';
this.cantidadNuevoProducto = '';
}
},
aumentarCantidad(index){
this.productos[index].cantidad++;
localStorage.setItem('productos-local', JSON.stringify(this.productos));
},
disminuirCantidad(index){
if(this.productos[index].cantidad > 0){
this.productos[index].cantidad--;
localStorage.setItem('productos-local', JSON.stringify(this.productos));
}
},
habilitarEditar(index){
this.productos[index].editar = true;
},
eliminarProducto(index){
this.productos.splice(index, 1);
localStorage.setItem('productos-local', JSON.stringify(this.productos));
},
editarProducto(index){
localStorage.setItem('productos-local', JSON.stringify(this.productos));
this.productos[index].editar = false;
}
Donde cada método se describe a continuación.
- Agregar Producto: este método crea un nuevo producto, utlizándo para ello las variables auxiliares: nombreNuevoProducto, cantidadNuevoProducto. Termina por guardar todos los productos en el LocalStorage.
- AumentarCantidad: este método aumenta en 1 la cantidad de un producto específico. Termina por guardar todos los productos en el LocalStorage.
- DisminuírCantidad: este método disminuye en 1 la cantidad de un producto específico siempre y cuando éste sea mayor que cero. Termina por guardar todos los productos en el LocalStorage.
- HabilitarEditar: Este método habilita una variable auxiliar que se llama 'editar' dentro de cada producto que es usado para activar el botón de 'guardar' y el casillero del nombre de producto dentro de cada fila de la tabla.
- EliminarProducto: Este método elimina un producto específico dentro del objeto de productos. Termina por guardar todos los productos en el LocalStorage.
- EditarProducto: Empieza por guardar todos los productos en el LocalStorage. Posterior cambia la variable 'editar' dentro del producto para desactivar el casillero y el botón de guardar.
Como hemos visto, utilizamos el LocalStorage en cada paso para guardar un JSON con los productos dentro de un valor denominado "productos-local". Esta variable del LocalStorage deberá ser leída en la carga de los elementos para ser mostrados al inicio. En este sentido, ocupamos un objeto denominado 'created' que podemos usar para el efecto. Este objeto es un método que forma parte del ciclo de vida de Vue.js.
Para una mejor comprensión del ciclo de vida de Vue.js visitar el siguiente enlace.
De esta forma, colocamos el objeto 'created' dentro de la instancia de Vue del archivo main.js de la siguiente manera:
created: function(){
let dbData = JSON.parse(localStorage.getItem('productos-local'));
if(dbData === null){
this.productos = [];
}else{
this.productos = dbData;
}
}
Donde cargamos los datos del LocalStorage con el nombre del valor y los pasamos dentro del objeto 'productos'.
Como parte final, vamos a colocar las siguientes etiquetas HTML dentro del div que contiene el id="app":
<h2>{{titulo}}</h2>
<div class="input-group mt-5">
<div class="input-group-prepend">
<span class="input-group-text text-dark">Nombre / Cantidad</span>
</div>
<input type="text" aria-label="Nombre" class="form-control" v-model="nombreNuevoProducto">
<input type="number" aria-label="Cantidad" class="form-control" v-model="cantidadNuevoProducto">
<div class="input-group-append">
<button class="btn btn-success" type="button" id="button-addon2" @click="agregarProducto">Agregar</button>
</div>
</div>
<table class="table mt-5">
<thead class="thead-dark">
<tr>
<th scope="col" v-for="columna of columnas">{{columna}}</th>
</tr>
</thead>
<tbody>
<tr v-for="(producto, index) of productos">
<th scope="row">{{index+1}}</th>
<td><input class="form-control" type="text" v-bind:disabled="!producto.editar" v-model="producto.nombre"></td>
<td>{{producto.cantidad}}</td>
<td>
<span v-if="producto.cantidad <= 0">AGOTADO</span>
<span v-if="producto.cantidad > 0">EN STOCK</span>
</td>
<td>
<button class="btn btn-primary" @click="aumentarCantidad(index)">+</button>
<button class="btn btn-warning" @click="disminuirCantidad(index)">-</button>
<button class="btn btn-info" v-bind:disabled="!producto.editar" @click="editarProducto(index)">GUARDAR</button>
<button class="btn btn-secondary" @click="habilitarEditar(index)">EDITAR</button>
<button class="btn btn-danger" @click="eliminarProducto(index)">x</button>
</td>
</tr>
</tbody>
</table>
De esta manera, tendremos definido una página con la siguiente información:
CRUD con Vue.js
Acordémonos que localStorage guarda los datos de manera local del lado del cliente y pueden ser eliminados el borrar los datos del navegador.
Para una mayor información acerca de LocalStorage, visita el siguiente enlace.
Recuerda descargar los archivos para que pruebes por ti mismo las facilidades y rapidez que Vue.js actúa dentro del front-end.
Enlace de Descarga: https://github.com/nano-bytes/vuejs
No te olvides de dejar tus dudas y comentarios al respecto y hasta una próxima entrega.