-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #63 from dbssman/feature/60-add-context-provider-a…
…s-composable 💉 Add context provider and tests
- Loading branch information
Showing
8 changed files
with
234 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
# useFormContext | ||
|
||
`useFormContext` is a composable to access all the exposed functionalities of `useFormHandler` in any descendant of the handlers subtree is used. By this we avoid drilling the things we need down. | ||
|
||
## How it works | ||
|
||
`useFormContext` makes use of the [Vue 3 Provide/Inject](https://vuejs.org/guide/components/provide-inject.html) feature to directly provide the exposed features of `useFormHandler` to all the subtree. | ||
|
||
As you can imagine, `useFormContext` and `useFormHandler` share the same return, nevertheless, the ancestor who consumes useFormHandler will rule things like `initialValues`, `validationMode`.... | ||
|
||
## Example: | ||
|
||
```vue | ||
<!-- Parent.vue component --> | ||
<template> | ||
<form @submit.prevent="handleSubmit(successFn)"> | ||
<input v-bind="register('firstName')" /> | ||
<input v-bind="register('lastName')" /> | ||
<Child></Child> | ||
<button type="submit">Submit</button> | ||
</form> | ||
</template> | ||
<script setup lang="ts"> | ||
import { useFormHandler } from 'vue-form-handler' | ||
import Child from './Child.vue' | ||
const { handleSubmit, register } = useFormHandler(); | ||
const successFn = (form: Record<string, any>) => { | ||
console.log({ form }) | ||
} | ||
</script> | ||
``` | ||
|
||
```vue | ||
<!-- Child.vue component --> | ||
<template> | ||
<input v-bind="register('anotherField')" /> | ||
<GrandChild></GrandChild> | ||
</template> | ||
<script setup lang="ts"> | ||
import { useFormContext } from 'vue-form-handler' | ||
import GrandChild from './GrandChild.vue' | ||
const { register } = useFormContext() | ||
</script> | ||
``` | ||
|
||
```vue | ||
<!-- GrandChild.vue component --> | ||
<template> | ||
<input v-bind="register('anotherField2')" /> | ||
</template> | ||
<script setup lang="ts"> | ||
import { useFormContext } from 'vue-form-handler' | ||
const { register } = useFormContext() | ||
</script> | ||
``` | ||
|
||
Feel free to play with it, you can also combine `register` and `build` approaches for the same form, within the same and in different files | ||
|
||
::: warning | ||
Be aware that for a basic and usual functionality, We provide with a default key, If you have more than one `useFormHandler` usage in the same tree, the `injection keys` will collide, so you'll need to pass a specific one to `useFormHandler` and then to its consequent consumer, i.e: | ||
|
||
:::details | ||
```vue | ||
<!-- Parent.vue component --> | ||
<template> | ||
<div> | ||
<form @submit.prevent="handleSubmit(successFn)"> | ||
<input v-bind="register('firstName')" /> | ||
<input v-bind="register('lastName')" /> | ||
<Child></Child> | ||
<button type="submit">Submit</button> | ||
</form> | ||
<form @submit.prevent="handleSubmit2(successFn)"> | ||
<input v-bind="register2('firstName')" /> | ||
<input v-bind="register2('lastName')" /> | ||
<AnotherChild></AnotherChild> | ||
<button type="submit">Submit</button> | ||
</form> | ||
</div> | ||
</template> | ||
<script setup lang="ts"> | ||
import { useFormHandler } from 'vue-form-handler' | ||
import Child from './Child.vue' | ||
import AnotherChild from './AnotherChild.vue' | ||
const { handleSubmit, register } = useFormHandler({ injectionKey: 'form1' }); | ||
const { handleSubmit: handleSubmit2, register: register2 } = useFormHandler({ injectionKey: 'form2' }); | ||
const successFn = (form: Record<string, any>) => { | ||
console.log({ form }) | ||
} | ||
</script> | ||
``` | ||
|
||
```vue | ||
<!-- Child.vue component --> | ||
<template> | ||
<input v-bind="register('anotherField')" /> | ||
</template> | ||
<script setup lang="ts"> | ||
import { useFormContext } from 'vue-form-handler' | ||
const { register } = useFormContext('form1') | ||
</script> | ||
``` | ||
|
||
```vue | ||
<!-- AnotherChild.vue component --> | ||
<template> | ||
<input v-bind="register('anotherField')" /> | ||
</template> | ||
<script setup lang="ts"> | ||
import { useFormContext } from 'vue-form-handler' | ||
const { register } = useFormContext('form2') | ||
</script> | ||
``` | ||
::: | ||
|
||
::: tip | ||
Please refer to [Working with Symbol Keys](https://vuejs.org/guide/components/provide-inject.html#working-with-symbol-keys) for a quick read and understanding how provide/inject is intended to be used, and a correct way of defining your keys, as passing plain strings might not be the best approach, but rather using `Symbol` | ||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export * from './FormHandler' | ||
export * from './useFormHandler' | ||
export * from './useFormContext' | ||
export * from './types' | ||
export * from './constants' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { defineComponent } from '@vue/runtime-core' | ||
import { mount } from '@vue/test-utils' | ||
import { expect, it, describe } from 'vitest' | ||
import { | ||
useFormContext, | ||
useFormHandler, | ||
FormHandler, | ||
InjectionKey, | ||
} from '../index' | ||
|
||
describe('useFormContext', () => { | ||
const registerComponents = (injectionKey?: InjectionKey) => { | ||
const Child = defineComponent({ | ||
template: `<template> | ||
{{props}} | ||
</template>`, | ||
setup() { | ||
const props = useFormContext(injectionKey) | ||
return { | ||
props, | ||
} | ||
}, | ||
}) | ||
const Parent = defineComponent({ | ||
template: `<template> | ||
<Child></Child> | ||
</template>`, | ||
components: { Child }, | ||
setup() { | ||
useFormHandler({ injectionKey }) | ||
}, | ||
}) | ||
|
||
return Parent | ||
} | ||
it('should provide values and formState', () => { | ||
expect(FormHandler).toBeTruthy() | ||
const Parent = registerComponents() | ||
const wrapper = mount(Parent, { | ||
slots: { | ||
default: `<template #default="props"> | ||
{{props}} | ||
</template> | ||
`, | ||
}, | ||
}) | ||
expect(wrapper.html()).toContain('values') | ||
expect(wrapper.html()).toContain('formState') | ||
}) | ||
it('should work with string injection keys', () => { | ||
expect(FormHandler).toBeTruthy() | ||
const Parent = registerComponents('test') | ||
const wrapper = mount(Parent, { | ||
slots: { | ||
default: `<template #default="props"> | ||
{{props}} | ||
</template> | ||
`, | ||
}, | ||
}) | ||
expect(wrapper.html()).toContain('values') | ||
expect(wrapper.html()).toContain('formState') | ||
}) | ||
it('should work with Symbol injection keys', () => { | ||
expect(FormHandler).toBeTruthy() | ||
const Parent = registerComponents(Symbol('test')) | ||
const wrapper = mount(Parent, { | ||
slots: { | ||
default: `<template #default="props"> | ||
{{props}} | ||
</template> | ||
`, | ||
}, | ||
}) | ||
expect(wrapper.html()).toContain('values') | ||
expect(wrapper.html()).toContain('formState') | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { inject } from '@vue/runtime-core' | ||
import { defaultInjectionKey } from './constants' | ||
import { FormHandlerReturn, InjectionKey } from './types' | ||
|
||
export const useFormContext = ( | ||
key: InjectionKey = defaultInjectionKey | ||
): FormHandlerReturn => inject(key) as FormHandlerReturn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5455ecb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
vue-form-handler – ./
vue-form-handler-git-master-danielerequejo-gmailcom.vercel.app
www.vue-form-handler.com
vue-form-handler-danielerequejo-gmailcom.vercel.app
vue-form-handler.vercel.app
vue-form-handler.com