Paso a paso: implementar interfaces Draggables con VueJS
February 9, 2021 Compartir
Implementación de una interfaz animada con elementos draggables (arrastrar y soltar) con VueJS.
Live demo
Código fuente
Prerequisitos
Para este tutorial consideraremos que ya tienes conocimientos básicos de Vue JS y que ya sabes cómo integrar TailwindCSS a Vue JS. En resumen debes estar familiarizado con:
- Funcionamiento básico de TailwindCSS.
- Configuración inicial de un proyecto Vue a través de Vue CLI
- Integración de Tailwind a un proyecto Vue. 👉 Tutorial en inglés
- Nociones básicas de Vue: anatomía de un archivo .vue, cómo trabajar con datos y propiedades en componentes, métodos, renderizado condicional, eventos.
Metas
Construiremos una aplicación sencilla que consistirá en un listado básico de usuarios. Veremos cómo lograr la funcionalidad de "arrastrar y soltar" elementos en el DOM.
PASOS PRELIMINARES
1. Diseño inicial y color de fondo
Editaremos el archivo App.vue el cual corresponde al componente principal de
nuestra aplicación y modificaremos la seccion <template>
con lo siguiente:
<template>
<div id="app" class="min-h-screen w-screen bg-gray-600 flex items-center justify-center">
</div>
</template>
Con las clases de Tailwind utilizadas estamos estableciendo el color de fondo y centrando todo en la página.
Todas las clases de CSS que vamos a utilizar corresponden al conjunto de clases predeterminado de Tailwind. Puede encontrarlos en la documentación oficial, sin embargo, la mayoría de ellos se explican por sí mismas.
2. Listado de usuarios
Para nuestro ejemplo, el listado de usuarios será declarado e inicializado dentro
del objeto data
del componente principal App.vue
data() {
return {
users: [
{
id: 1,
name: "Evan You",
avatar: "https://pickaface.net/gallery/avatar/unr_sample_161118_2054_ynlrg.png",
},
{
id: 2,
name: "Taylor Otwell",
avatar: "https://pickaface.net/gallery/avatar/freud51c8b3f65e7dc.png"
},
{
id: 3,
name: "Steve Jobs",
avatar: "https://pickaface.net/gallery/avatar/Opi51c74d0125fd4.png"
},
{
id: 4,
name: "Linus Torvalds",
avatar: "https://pickaface.net/gallery/avatar/unr_yassine_191124_2012_3gngr.png"
},
{
id: 5,
name: "Bill Gates",
avatar: "https://pickaface.net/gallery/avatar/elmedinilla541c03412955c.png"
}
]
}
},
Ahora que ya tenemos la lista de usuarios en nuestra instancia de Vue, podemos mostrarla iterando sobre cada uno de los elementos del array:
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }}
</li>
</ul>
Y obtenemos...
Aplicando clases de Tailwind comenzaremos a darle estilos a nuestro listado:
<ul class="w-full max-w-md">
<li v-for="user in users"
:key="user.id"
class="p-4 mb-3 flex justify-between items-center bg-white shadow rounded-lg cursor-move">
{{ user.name }}
</li>
</ul>
Nuestro listado quedaría de esta forma:
Ahora agregaremos algunos detalles más como el avatar y botones de acción.
Como ya tenemos las URL del avatar en nuestro listado de usuarios, los añadiremos a nuestra tarjeta:
<li v-for="user in users"
:key="user.id"
class="p-4 mb-3 flex justify-between items-center bg-white shadow rounded-lg cursor-move">
<div class="flex items-center">
<img class="w-10 h-10 rounded-full" :src="user.avatar" :alt="user.name">
<p class="ml-2 text-gray-700 font-semibold font-sans tracking-wide">{{ user.name }}</p>
</div>
</li>
Para los botones de acción vamos a usar un conjunto de iconos SVG que se pueden importar como componentes a través de la libreria vue-feather-icons. Para ello debemos instalarla en nuestro proyecto:
npm install vue-feather-icons
Ahora debemos importar los componentes que utilizaremos de la librería que acabamos de instalar:
// En el archivo src/App.vue
<script>
import { Edit3Icon, TrashIcon } from "vue-feather-icons";
export default {
components: {
Edit3Icon,
TrashIcon
}
}
</script>
Ya podemos hacer uso de los nuevos componentes en el template html. Añadiremos los botones para las acciones editar y eliminar:
<div class="flex">
<button
class="p-1 focus:outline-none focus:shadow-outline text-teal-500 hover:text-teal-600"
title="Editar usuario">
<Edit3Icon/>
</button>
<button
class="p-1 focus:outline-none focus:shadow-outline text-red-500 hover:text-red-600"
title="Eliminar usuario">
<TrashIcon/>
</button>
</div>
Y nuestro listado de usuarios ahora se ve así 🤩
IMPLEMENTANDO DRAG & DROP
Hemos llegado al punto de este tutorial, implementaremos la funcionalidad de arrastrar y soltar elementos en el DOM:
Para lograr este efecto utilizaremos la biblioteca Vue Draggable, la cual debemos instalar en nuestra aplicación:
npm install vuedraggable
Luego la importamos en nuestro componente App.vue
:
<script>
import { Edit3Icon, TrashIcon } from "vue-feather-icons";
import Draggable from 'vuedraggable'
export default {
name: 'App',
components: {
Edit3Icon,
TrashIcon,
Draggable,
}
}
</script>
Ya estamos listos para hacer que nuestro listado soporte Drag & Drop. Sólo
tenemos que "envolverlo" dentro de nuestro nuevo componente. Reemplazaremos las
etiquetas <ul>
por <Draggable>
de la siguiente forma:
<Draggable :list="users">
<li v-for="user in users"
:key="user.id">
<!-- ... -->
</li>
</Draggable>
Nota que el componente Draggable debe recibir datos para una propiedad llamada
list
, que en nuestro caso corresponde a nuestro array de usuarios
<Draggable :list="users">
Por otro lado debemos decirle al componente cuál es el elemento al cual se le
aplicará el efecto, en nuestro caso es el elemento <ul>
, así como los estilos
que ya tenía:
<Draggable :list="users" tag="ul" class="w-full max-w-md" ghost-class="moving-card" :animation="200">
La propiedad ghost-class
le otorga a nuestro listado una animación suave. Para
que funcione debemos añadir los siguientes estilos a nuestro componente App.vue:
<style lang="scss">
.moving-card {
@apply opacity-50 bg-gray-100 border border-blue-500;
}
</style>
¡Hemos terminado!
Aquí está nuestro componente App completo
// Archivo src/App.vue
<template>
<div id="app" class="min-h-screen w-screen bg-gray-600 flex items-center justify-center">
<Draggable v-if="users.length > 0" ghost-class="moving-card" tag="ul" class="w-full max-w-md" :list="users" :animation="200">
<li v-for="user in users"
:key="user.id"
class="p-4 mb-3 flex justify-between items-center bg-white shadow rounded-lg cursor-move">
<div class="flex items-center">
<img class="w-10 h-10 rounded-full" :src="user.avatar" :alt="user.name">
<p class="ml-2 text-gray-700 font-semibold font-sans tracking-wide">{{ user.name }}</p>
</div>
<div class="flex">
<button
class="p-1 focus:outline-none focus:shadow-outline text-teal-500 hover:text-teal-600"
title="Editar usuario">
<Edit3Icon/>
</button>
<button
class="p-1 focus:outline-none focus:shadow-outline text-red-500 hover:text-red-600"
title="Eliminar usuario"
v-on:click="deleteUser(user)">
<TrashIcon/>
</button>
</div>
</li>
</Draggable>
</div>
</template>
<script>
import { Edit3Icon, TrashIcon } from "vue-feather-icons";
import Draggable from 'vuedraggable'
export default {
name: 'App',
components: {
Draggable,
Edit3Icon,
TrashIcon
},
data() {
return {
users: [
{
id: 1,
name: "Evan You",
avatar: "https://pickaface.net/gallery/avatar/unr_sample_161118_2054_ynlrg.png",
},
{
id: 2,
name: "Taylor Otwell",
avatar: "https://pickaface.net/gallery/avatar/freud51c8b3f65e7dc.png"
},
{
id: 3,
name: "Steve Jobs",
avatar: "https://pickaface.net/gallery/avatar/Opi51c74d0125fd4.png"
},
{
id: 4,
name: "Linus Torvalds",
avatar: "https://pickaface.net/gallery/avatar/unr_yassine_191124_2012_3gngr.png"
},
{
id: 5,
name: "Bill Gates",
avatar: "https://pickaface.net/gallery/avatar/elmedinilla541c03412955c.png"
}
]
}
},
}
</script>
<style lang="scss">
.moving-card {
@apply opacity-50 bg-gray-100 border border-blue-500;
}
</style>
Conclusión
En este artículo hemos visto cómo implementar elementos Draggables utilizando Vue JS. Puedes ver el live-demo en este enlace. También puedes descargar aquí el código fuente del proyecto. En el repositorio hay algunas otras mejoras como las funcionalidades de editar, eliminar y agregar un nuevo usuario; también se mejoró un poco la estructura del proyecto creando un componente separado para las tarjetas de usuario. Clónalo y sigue haciéndole mejoras a la aplicación, ¡tu imaginación es el límite! 😉.
Autor
Hola 👋, Soy Alejandro, un desarrollador de software que disfruta crear y mejorar herramientas que resuelvan problemas y hagan que la vida de las personas sea más sencilla, bella y cómoda. Algunas veces escribo sobre las cosas que he aprendido con el tiempo. Espero que el contenido te sea de ayuda.