Skip to content

Crear Composable useFormTask.ts

Después de haber visto las dos secciones anteriores ya deberíamos de estar un poco familiarizado con los composables.

Ya creamos un composable que no recibe argumentos y otro que recibe las props como primer argumento. No obstante, aún nos falta un escenario donde tengamos que pasar también el contexto o parte de él.

Creando el archivo ./composables/useFormTask.ts

Nota

No se preocupe si aún no se encuentra muy familiarizado con TypeScript, porque gracias a los complementos de vscode (Vue Language Features "Volar" y TypeScript Vue Plugin "Volar") estos nos ayuda con el soporte.

Tenga en cuenta que aquí estaremos pasando tanto las propiedades como el contexto. En este caso, los eventos ctx.emit.

📃./composables/useFormTask.ts

ts
import { ref } from 'vue'
import type { Task } from '@/types'

type Props = {
  readonly task?: Record<string, any>;
  readonly onSubmit?: ((...args: any[]) => any);
}
type Ctx = {
  emit: (event: "submit", ...args: any[]) => void;
}

export default (props: Props, ctx: Ctx) => {
  const form = ref(props.task as Task)
  const submit = () => ctx.emit('submit', form.value )

  return {
    form,

    submit
  }
}

Gracias a TypeScript, este tipado sirve tanto para el verificado de tipos como para tener alguna documentación referente a lo que recibe la función.

Limpiando el archivo ./components/FormTask.vue

Solo nos queda importar el composable useFormTask e instanciarlo para poder implementar sus propiedades y funciones de retorno.

Tenga en cuenta que las props y el ctx deben ser pasadas respectivamente como argumento a la función setup(), ya que las necesitamos para pasarlas al composable useFormTask.

📃./components/FormTask.vue

vue
<script lang="ts">
import { defineComponent } from 'vue'
import useFormTask from '../composables/useFormTask'

export default defineComponent({
  props: {
    task: Object    
  },
  emits: ['submit'],
  setup(props, ctx) {
    const {
      form,

      submit
    } = useFormTask(props, ctx)

    return {
      form,

      submit
    }
  }
})
</script>

<template>
  <form @submit.prevent="submit">
    <div class="m-2">
      <label>Title</label>
      <input type="text" v-model="form.title">
    </div>

   <div class="m-4">
      <label>Description</label>
      <textarea v-model="form.description"></textarea>
    </div>

    <div class="m-4">
      <label>Done</label>
      <input type="checkbox" v-model="form.done"/>
    </div>

    <button type="submit" class="btn btn-primary m-2">
      Save
    </button>
  </form>
</template>

De esta forma todo queda mucho más limpio, reutilizable y testeable.