Skip to content

Instantly share code, notes, and snippets.

@SkyaTura
Last active August 5, 2022 20:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SkyaTura/b2f5e8b31255ad96f121a304a749ec64 to your computer and use it in GitHub Desktop.
Save SkyaTura/b2f5e8b31255ad96f121a304a749ec64 to your computer and use it in GitHub Desktop.
Formulário com composable de provide/inject Vue3
<script setup lang="ts">
import PersonFormSectionAge from './PersonFormSectionAge.vue'
import type { Person } from '~/types'
const form = useFormInject<Person>('form.person')
</script>
<template lang="pug">
v-form
v-text-field(v-model="form.value.firstName" label="First name")
v-text-field(v-model="form.value.lastName" label="Last name")
PersonFormSectionAge
</template>
<script setup lang="ts">
import type { Person } from '~/types'
const form = useFormInject<Person>('form.person')
</script>
<template lang="pug">
section
.text-h6 Fancy section here
.text-body Some descriptions
v-text-field(v-model.number="form.value.age" type="number" label="Age")
</template>
import { useAxios } from './useAxios'
import { ref, provide, inject } from 'vue'
import type { Axios } from 'axios'
import type { Ref } from 'vue'
interface FormProviderOptions<T> {
model: () => T
value?: Ref<T>
submit?: (axios: Axios, value: T) => Promise<void>
fetch?: (axios: Axios) => Promise<T>
}
interface FormProvider<T> {
value: Ref<T>
submit: () => Promise<void>
fetch: () => Promise<T>
clear: () => void
}
export function useFormProvide<T>(providerKey: string, options: FormProviderOptions<T>) {
const value = options.value ?? (ref(options.model()) as Ref<T>)
const axios = useAxios()
const provider: FormProvider<T> = {
value,
submit: () => options.submit?.(axios, value.value as T),
fetch: async () => {
if (!options.fetch) return null
const newValue = await options.fetch(axios)
value.value = newValue as T
return newValue
},
clear: () => {
value.value = options.model()
},
}
provide<FormProvider<T>>(providerKey, provider)
return provider
}
export function useFormInject<T>(providerKey: string) {
return inject<FormProvider<T>>(providerKey)
}
<script setup lang="ts">
import PersonForm from '~/components/PersonForm.vue'
import { personModel } from '~/types'
import type { Person } from '~/types'
const form = useFormProvide<Person>('form.person', {
model: personModel,
})
</script>
<template lang="pug">
v-card
v-card-title Person Form
v-card-text
PersonForm
</template>
<script setup lang="ts">
import PersonForm from '~/components/PersonForm.vue'
import { personModel } from '~/types'
import type { Person } from '~/types'
const person = ref<Person>({
/* ... */
})
const form = useFormProvide<Person>('form.person', {
model: personModel,
value: person,
submit: (axios, value) => axios.post('/people', value),
})
onMounted(() => form.fetch())
</script>
<template lang="pug">
v-card
v-card-title Person Form
v-card-text
PersonForm
v-card-actions
v-btn(@click="form.clear") Clear
v-btn(@click="form.submit") Submit
</template>
<script setup lang="ts">
import PersonForm from '~/components/PersonForm.vue'
import { personModel } from '~/types'
import type { Person } from '~/types'
const route = useRoute()
const form = useFormProvide<Person>('form.person', {
model: personModel,
fetch: (axios) => axios.get(`/people/${route.params.id}`),
submit: (axios, { id, ...value }) => axios.patch(`/people/${id}`, value),
})
onMounted(() => form.fetch())
</script>
<template lang="pug">
v-card
v-card-title Person Form
v-card-text
PersonForm
v-card-actions
v-btn(@click="form.clear") Clear
v-btn(@click="form.submit") Submit
</template>
<script setup lang="ts">
import PersonForm from '~/components/PersonForm.vue'
import { personModel } from '~/types'
import type { Person } from '~/types'
const form = useFormProvide<Person>('form.person', {
model: personModel,
submit: (axios, value) => axios.post('/people', value),
})
</script>
<template lang="pug">
v-card
v-card-title Person Form
v-card-text
PersonForm
v-card-actions
v-btn(@click="form.clear") Clear
v-btn(@click="form.submit") Submit
</template>
export interface Person {
firstName: string
lastName: string
age: number
}
export const personModel = (): Person => ({
firstName: '',
lastName: '',
age: 0,
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment