Cuando necesitemos acompañar al usuario durante una acción (por ejemplo, un trámite o un proceso compuesto por varias pantallas), guiándolo paso a paso y haciendo la interacción más clara, utilizaremos un asistente con pasos. Para ello, haremos uso del componente fwjsStepper.
Este componente permite dividir un flujo en etapas, mostrar en qué paso se encuentra el usuario y facilitar la navegación entre pasos, mejorando la comprensión del proceso y reduciendo errores.
En esencia, el diseño del componente será algo como lo siguiente:
Import
import fwjsStepper from '@/app/shared/components/fwjsStepper.vue';
Modos de uso
Para que fwjsStepper sea más flexible, se ofrecen dos modos de uso:
- Con una única ruta: todo el proceso comparte la misma URL y el asistente va cambiando de paso internamente.
- Con una ruta por cada paso: cada paso tiene su propia URL, así que se puede entrar directamente en un paso concreto.
¿Y cuál habría que usar en cada caso? Depende de si el usuario puede dejar el proceso a medias y retomarlo más tarde.
- Si sí, lo más recomendable es usar una ruta por paso, porque así podrá retomar el proceso justo donde lo dejó (incluso guardando la URL o accediendo desde un enlace).
- Si no (por ejemplo, es un flujo corto y seguido), normalmente con una única ruta es suficiente.
Modo con ruta única
En este modo, todo el asistente se mantiene dentro de la misma ruta. El cambio de pasos se gestiona de forma interna, sin modificar la URL, por lo que es ideal para flujos cortos y seguidos.
Ejemplo
<template>
<fwjsStepper :items="items">
<template #step-1="{ prevPage, nextPage, restart, updateHeader }">
<!-- Contenido del primer paso -->
</template>
<template #step-2="{ prevPage, nextPage, restart, updateHeader }">
<!-- Contenido del segundo paso -->
</template>
<template #step-3="{ prevPage, nextPage, restart, updateHeader }">
<!-- Contenido del tercer paso -->
</template>
</fwjsStepper>
</template>
<script lang="ts" setup>
...
const items = computed(() => [
{
title: t('step_1'),
subtitle: t('step_1_subtitle'),
},
{
title: t('step_2'),
subtitle: t('step_2_subtitle'),
},
{
title: t('step_3'),
subtitle: t('step_3_subtitle'),
},
]);
...
</script>
Slots
Para este modo de uso, el componente tendrá los siguientes slots:
step-N: por cada elemento definido en la propiedad items, habrá que crear un slot con el contenido del paso correspondiente del asistente.
Cada slot step-N recibe estas propiedades:
prevPage: función para volver al paso anterior.
nextPage: función para avanzar al paso siguiente.
restart: función para reiniciar el asistente y volver al primer paso.
updateHeader: función para actualizar el contenido del header del paso actual. Recibe un objeto con las propiedades title y subtitle.
Eventos
En este modo de uso no es necesario gestionar eventos, ya que la navegación y el control del asistente se realizan a través de las propiedades expuestas en los slots.
Modo con rutas por paso
En este modo, cada paso del asistente tiene su propia ruta. Esto permite acceder directamente a un paso concreto y facilita retomar el proceso más adelante (por ejemplo, guardando la URL o entrando desde un enlace).
Ejemplo
// Archivo que incluye el asistente MiStepperView.vue
<template>
<fwjsStepper :items="items" :restartOnRefresh="true" />
</template>
<script lang="ts" setup>
...
const items = computed(() => [
{
title: t('step_1'),
subtitle: t('step_1_subtitle'),
to: '/seccion/asistente/paso-1',
},
{
title: t('step_2'),
subtitle: t('step_2_subtitle'),
to: '/seccion/asistente/paso-2',
},
{
title: t('step_3'),
subtitle: t('step_3_subtitle'),
to: '/seccion/asistente/paso-3',
},
]);
...
</script>
// Archivo module.routes
export default [
...
{
path: '/seccion/asistente',
name: 'SeccionMiStepper',
component: MiStepperView,
meta: {
...
},
children: [
{
path: 'paso-1' // /seccion/asistente/paso-1,
name: 'SeccionMiStepperPaso1',
component: MiStepperPaso1,
},
{
path: 'paso-3' // /seccion/asistente/paso-2,
name: 'SeccionMiStepperPaso2',
component: MiStepperPaso2,
},
{
path: 'paso-3' // /seccion/asistente/paso-3,
name: 'SeccionMiStepperPaso3',
component: MiStepperPaso3,
},
],
},
...
];
Slots
En este modo de uso no es necesario utilizar slots, ya que el contenido y la navegación de cada paso se gestionan a través de sus rutas (un componente por paso).
Eventos
Para controlar la navegación del asistente y los cambios en el header, los componentes de cada paso deberán emitir los siguientes eventos:
prev-page: evento para volver al paso anterior.
next-page: evento para avanzar al paso siguiente.
restart: evento para reiniciar el asistente y volver al primer paso.
update-header: evento para actualizar el contenido del header del paso actual. Envía un objeto con las propiedades title y subtitle.
Propiedades
| Propiedad | Tipo | Default | Descripción |
|---|---|---|---|
| class | String | Nombre de la clase CSS para añadir al componente principal. | |
| items | StepperItem[] | Array con la información de los pasos que tendrá el asistente. {
title?: 'Título del paso concreto',
subtitle?: 'Subtítulo del paso concreto',
to?: 'Ruta del paso concreto'
}
| |
| title | String | Título por defecto del asistente. | |
| subtitle | String | Subtítulo por defecto del asistente. | |
| restartOnRefresh | Boolean | false | Si está habilitada, al recargar la página o al acceder directamente a un paso mediante la URL, el asistente ignorará ese paso y empezará desde el primer paso. |
Footer del step
Para que el footer sea coherente en todos los pasos del asistente, es importante respetar esta estructura:
- El contenedor del footer debe llevar la clase footer.
- La nota debe llevar la clase note.
- Los botones deben estar englobados en un contenedor con la clase footer__actions.
<template>
<fwjsStepper :items="items">
...
<template #step-3="{ prevPage, nextPage, restart, updateHeader }">
...
<div class="footer">
<!-- Para añadir notas en la parte izquierda -->
<span class="note note--lowercase note--required">
{{ t('campos_requeridos') }}
</span>
<!-- Para los botones, que irán a la derecha -->
<div class="footer__actions">
<Button ... />
<Button ... />
</div>
</div>
</template>
</fwjsStepper>
</template>