Cómo construir una tabla de datos editables en tiempo real en Vue.js

En las aplicaciones basadas en datos, se utiliza una tabla de datos para mostrar datos en formato tabular con la capacidad de editar y eliminar registros en su lugar. Cuando trabaja con Vue, existen diferentes componentes de código abierto que pueden usarse para agregar fácilmente una tabla de datos a su aplicación.

Hoy en día, muchas aplicaciones tienen funciones en tiempo real y es posible que se pregunte cómo puede sincronizar la edición y eliminación de datos en tiempo real. Hay tres opciones para esto:

  1. Utilice la API de WebSocket. Esta no es una buena opción si algunos de sus usuarios están usando navegadores que aún no son compatibles con WebSocket.
  2. Utilice una biblioteca que abstraiga estas diferencias entre navegadores con un mecanismo de reserva, como Socket.IO, SignalR y SockJS. Con esta opción, tendría que administrar el servidor que maneja una gran cantidad de conexiones abiertas y lidiar con el escalado.
  3. Utilice un servicio que proporcione una biblioteca que haga lo mismo que la opción anterior, pero administre el servidor y se escale de manera adecuada. Esta es una opción preferible para empresas y equipos que están adoptando (o han adoptado) el enfoque sin servidor.

Le mostraré cómo crear una tabla de datos editables en tiempo real en Vue.js usando Hamoni Sync como el servicio de sincronización de estado en tiempo real. La siguiente imagen muestra lo que construiremos:

Para seguir adelante, deberá tener algunos conocimientos básicos de Vue. Si no tiene conocimiento de Vue, puede leer mi publicación anterior para ponerse al día con Vue.js. También necesitará las siguientes herramientas:

  1. Node.js & npm (siga el enlace para descargar un instalador para su sistema operativo)
  2. Vue CLI para crear un nuevo proyecto de Vue. Si no tiene esto, ejecútelo npm install -g [email protected]desde la línea de comandos para instalarlo.

Configurar el proyecto

Configuraremos el proyecto usando la CLI de Vue y una plantilla de Vuetify. Abra la línea de comando y ejecute el comando vue init vuetifyjs/simple realtime-datatable-vue. Se le pedirá un nombre y un autor, así que acepte el valor predeterminado presionando Intro para cada mensaje. Esto creará un andamio de un nuevo proyecto de Vue con un solo index.htmlarchivo.

Este archivo contiene referencias de secuencias de comandos a Vue y Vuetify. Vuetify es un componente de diseño de materiales para Vue.js. Tiene un v-data-tablecomponente con funciones de clasificación, búsqueda, paginación, edición en línea, información sobre herramientas de encabezado y selección de filas.

Agregar el componente de la tabla de datos

Abra el archivo index.htmlcon su editor de texto (o IDE). Reemplace el contenido de la línea 50 con lo siguiente:

 New Item   {{ formTitle }}                         Cancel Save      {{ props.item.name }}{{ props.item.calories }}{{ props.item.fat }}{{ props.item.carbs }}{{ props.item.protein }}  edit   delete  

El código anterior agrega un v-dialogcomponente para mostrar un cuadro de diálogo para recopilar datos para nuevos registros o editar un registro existente. Además, agrega el v-data-tableque representa la tabla. Necesitamos definir los datos y métodos utilizados por estos componentes. Después de la línea 126 , agregue el siguiente código a las propiedades de los datos:

dialog: false,headers: [ { text: 'Dessert (100g serving)', align: 'left', sortable: false, value: 'name' }, { text: 'Calories', value: 'calories' }, { text: 'Fat (g)', value: 'fat' }, { text: 'Carbs (g)', value: 'carbs' }, { text: 'Protein (g)', value: 'protein' }, { text: 'Actions', value: 'name', sortable: false }],desserts: [],editedIndex: -1,editedItem: { name: '', calories: 0, fat: 0, carbs: 0, protein: 0},defaultItem: { name: '', calories: 0, fat: 0, carbs: 0, protein: 0},listPrimitive: null

La dessertspropiedad de datos contendrá los datos que se mostrarán en la tabla. La editedItempropiedad contendrá los valores del registro que se está editando y editedIndexel índice del registro que se está editando.

Agregue las siguientes propiedades después de la datadefinición de propiedad, después de la línea 189 :

computed: { formTitle() { return this.editedIndex === -1 ? 'New Item' : 'Edit Item' }},
watch: { dialog(val)  this.close() },

Agregamos una propiedad computedy watch. La computedpropiedad define formTitlecuál le da al componente de diálogo un título basado en el valor de editedIndex. La watchpropiedad observa dialogcuando cambia su valor. Si el valor cambia a falso, llama a la función close()que se definirá más adelante.

Agregar Hamoni Sync

En este cruce necesitamos agregar Hamoni Sync. Se utiliza para sincronizar el estado de la aplicación y maneja la resolución de conflictos para evitar que un usuario anule los datos de otro usuario. Para usar Hamoni Sync, deberá registrarse para obtener una cuenta y una identificación de aplicación. Siga estos pasos para crear una aplicación en Hamoni.

  1. Regístrese e inicie sesión en el panel de Hamoni.
  2. Ingrese el nombre de su aplicación preferida en el campo de texto y haga clic en el botón crear. Esto debería crear la aplicación y mostrarla en la sección de la lista de aplicaciones.
  3. Haga clic en el botón "Mostrar ID de cuenta" para ver su ID de cuenta.

Debajo de la referencia del script a Vuetify en la línea 139 , agregue una referencia a Hamoni Sync:

Luego, debemos inicializar Hamoni Sync una vez que el componente Vue esté montado. Agregue una mountedpropiedad debajo de la watchpropiedad:

mounted: function () { let hamoni = new Hamoni("ACCOUNT_ID", "APP_ID");
 hamoni.connect().then(() => { hamoni .get("vue-table") .then(primitive => { this.listPrimitive = primitive this.desserts = [...primitive.getAll()] this.subscribeToUpdate() }).catch(error => { if (error === "Error getting state from server") { this.initialise(hamoni); } else { alert(error); } }) }).catch(alert)},

A partir del código anterior, inicializamos Hamoni Sync con una cuenta y un ID de aplicación. Reemplace los marcadores de posición de cadena con la cuenta y el ID de la aplicación del panel. Luego se conecta al servidor Hamoni llamando hamoni.connect()que devuelve una promesa.

Una vez conectados, llamamos hamoni.get()con el nombre del estado almacenado en Hamoni. Para recuperar un estado de Hamoni, debe haber sido creado; de lo contrario, devolverá un error. Lo que he hecho aquí es manejar este error dentro del bloque catch, de modo que llame a otra función para inicializar el estado en Hamoni Sync.

Si la llamada para obtener el estado de una aplicación tiene éxito, devuelve un objeto que se utilizará para modificar los datos contenidos en ese estado. Este objeto se denomina primitiva de sincronización. Hay tres tipos de primitivas de sincronización:

  1. Valor primitivo: este tipo de estado contiene información simple representada con tipos de datos como cadena, booleano o números. Es más adecuado para casos como el recuento de mensajes no leídos, alternar, etc.
  2. Objeto primitivo: el estado del objeto representa estados que se pueden modelar como un objeto JavaScript. Un ejemplo de uso podría ser almacenar la puntuación de un juego.
  3. Lista primitiva: contiene una lista de objetos de estado. Un objeto de estado es un objeto de JavaScript. Puede actualizar un elemento en función de su índice en la lista.

Hemos utilizado una lista primitiva para este ejemplo. Llamamos primitive.getAll()para conseguir el estado y pasárselo desserts. Después de eso, llama a la función subscribeToUpdate(). Esta función se utilizará para suscribirse a eventos de cambio de estado de Hamoni Sync.

Agregue el siguiente código después de la mountedpropiedad en la línea 215 :

methods: { initialise(hamoni) { hamoni.createList("vue-table", [ { name: 'Frozen Yogurt', calories: 159, fat: 6.0, carbs: 24, protein: 4.0 }, { name: 'Ice cream sandwich', calories: 237, fat: 9.0, carbs: 37, protein: 4.3 }, { name: 'Eclair', calories: 262, fat: 16.0, carbs: 23, protein: 6.0 } ]).then(primitive => { this.listPrimitive = primitive this.desserts = this.listPrimitive.getAll() this.subscribeToUpdate(); }).catch(alert) },
 subscribeToUpdate() { this.listPrimitive.onItemAdded(item => { this.desserts.push(item.value) })
 this.listPrimitive.onItemUpdated(item => { //update the item at item.index this.desserts.splice(item.index, 1, item.value); })
 this.listPrimitive.onItemDeleted(item => { //remove the item at item.index this.desserts.splice(item.index, 1); }) },
 editItem(item) { this.editedIndex = this.desserts.indexOf(item) this.editedItem = Object.assign({}, item) this.dialog = true },
 deleteItem(item) { const index = this.desserts.indexOf(item) confirm('Are you sure you want to delete this item?') && this.listPrimitive.delete(index) },
 close() { this.dialog = false setTimeout(() => { this.editedItem = Object.assign({}, this.defaultItem) this.editedIndex = -1 }, 300) },
 save() { if (this.editedIndex > -1) { this.listPrimitive.update(this.editedIndex, this.editedItem) } else { this.listPrimitive.push(this.editedItem) }
 this.close() }}

El código anterior define las funciones a las que hemos hecho referencia hasta ahora.

La initialise()función crea la lista primitiva con el nombre vue-table.

Las subscribeToUpdate()funciones contienen código para manejar cuando un elemento se agrega, actualiza o elimina de la lista primitiva.

La deleteItem()función elimina un elemento de la lista primitiva llamando listPrimitive.delete(index)con el índice del elemento a eliminar.

La save()función llama listPrimitive.push(editedItem)para agregar un nuevo elemento a la primitiva de la lista y llama listPrimitive.update(editedIndex, editedItem)para actualizar el registro en un índice determinado.

Este es todo el código que se necesita para lograr nuestro objetivo de una tabla de datos editable en tiempo real. Abra el index.htmlarchivo en su navegador y la aplicación estará lista para usar.

¡Eso es un envoltorio!

We’ve built a real-time editable data table in Vue.js. Hamoni Sync makes it easy to add real-time functionality. Both Vuetify and Hamoni Sync have npm packages if you’re working with a build system and using single file components. You can find the source code on GitHub.

Resources

  • Hamoni Sync (docs)
  • Vuetify
  • Vue CLI
  • Introduction to Vue.js essentials