Skip to content
This repository has been archived by the owner on Feb 28, 2023. It is now read-only.

Commit

Permalink
fix: local component injection refactor fixes #238 (#239)
Browse files Browse the repository at this point in the history
  • Loading branch information
marina-mosti authored Oct 2, 2021
1 parent d72473c commit 34fad96
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 17 deletions.
14 changes: 11 additions & 3 deletions packages/formvuelate/src/SchemaField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<component
v-if="schemaCondition"
v-bind="binds"
:is="field.component"
:is="component"
:modelValue="fieldValue"
@update:modelValue="update"
class="schema-col"
Expand All @@ -11,7 +11,7 @@

<script>
import { inject, computed, watch } from 'vue'
import { FIND_NESTED_FORM_MODEL_PROP, SCHEMA_MODEL_PATH, FORM_MODEL, UPDATE_FORM_MODEL, DELETE_FORM_MODEL_PROP } from './utils/constants'
import { FIND_NESTED_FORM_MODEL_PROP, SCHEMA_MODEL_PATH, FORM_MODEL, UPDATE_FORM_MODEL, DELETE_FORM_MODEL_PROP, INJECTED_LOCAL_COMPONENTS } from './utils/constants'
export default {
name: 'SchemaField',
Expand Down Expand Up @@ -66,6 +66,13 @@ export default {
return condition(formModel.value)
})
const component = computed(() => {
// Possible local components injected by user from SchemaFormFactory
const locals = inject(INJECTED_LOCAL_COMPONENTS, {})
return locals[props.field.component] || props.field.component
})
watch(schemaCondition, shouldDisplay => {
if (shouldDisplay) return
if (props.preventModelCleanupOnSchemaChange) return
Expand All @@ -77,7 +84,8 @@ export default {
binds,
fieldValue,
update,
schemaCondition
schemaCondition,
component
}
}
}
Expand Down
24 changes: 12 additions & 12 deletions packages/formvuelate/src/SchemaFormFactory.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { provide, inject } from 'vue'
import SchemaForm from './SchemaForm.vue'
import SchemaField from './SchemaField.vue'
import { isObject } from './utils/assertions'
import { INJECTED_LOCAL_COMPONENTS } from './utils/constants'

export default function SchemaFormFactory (plugins = [], components = null) {
// Copy the original SchemaForm setup
Expand Down Expand Up @@ -29,10 +30,18 @@ export default function SchemaFormFactory (plugins = [], components = null) {
// Call the original setup and preserve its results
const baseSchemaFormReturns = originalSetup(props, context)

if (components) {
// If user defined local components to be used inside the SchemaForm
// injected them so that SchemaField can use them if declared
if (!inject(INJECTED_LOCAL_COMPONENTS)) {
provide(INJECTED_LOCAL_COMPONENTS, components)
}
}

if (!plugins.length) return baseSchemaFormReturns
else {
// Apply plugins on the data returned
// by the original Schemaform
// by the original SchemaForm
return plugins.reduce(
(schemaFormReturns, plugin) => {
return plugin(schemaFormReturns, props, context)
Expand All @@ -42,21 +51,12 @@ export default function SchemaFormFactory (plugins = [], components = null) {
}
}

const SchemaFieldWithComponents = {
...SchemaField,
components: {
...components,
...SchemaField.components
}
}

return {
...SchemaForm,
props: schemaFormProps,
components: {
...components,
...SchemaForm.components,
SchemaField: SchemaFieldWithComponents
...SchemaForm.components
},
// Return a customized setup function with plugins
// as the new SchemaForm setup
Expand Down
2 changes: 2 additions & 0 deletions packages/formvuelate/src/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ export const UPDATE_FORM_MODEL = `${KEY}updateFormModel`
export const DELETE_FORM_MODEL_PROP = `${KEY}deleteFormModelProp`

export const LOOKUP_PARSE_SUB_SCHEMA_FORMS = `${KEY}parseSubSchemaForms`

export const INJECTED_LOCAL_COMPONENTS = `${KEY}injectedLocalComponents`
46 changes: 46 additions & 0 deletions packages/formvuelate/tests/e2e/specs/SchemaFormFactory.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,52 @@ import VeeValidatePlugin from '../../../../plugin-vee-validate/src/index'
import { BaseInput } from '../../utils/components'

describe('SchemaFormFactory', () => {
it('works with a blank plugin configuration and locally defined components', () => {
const SchemaFormWithPlugins = SchemaFormFactory([], { BaseInput })

mount({
components: { SchemaFormWithPlugins },
setup () {
const model = ref({
name: '',
pet: 'something',
nested: {

}
})

lookupSubSchemas(SchemaFormWithPlugins)
useSchemaForm(model)

const schemaRef = shallowRef({
name: {
component: 'BaseInput',
label: 'Your name'
},
pet: {
component: 'BaseInput',
label: 'Your pet'
},
nested: {
component: 'SchemaForm',
schema: {
game: {
component: 'BaseInput',
label: 'Videogame'
}
}
}
})

return () => h(SchemaFormWithPlugins, {
schema: schemaRef
})
}
})

cy.get('input').should('have.length', 3)
})

describe('with lookup plugin', () => {
it('parses subschema SchemaForm elements', () => {
const SCHEMA = [
Expand Down
31 changes: 29 additions & 2 deletions packages/formvuelate/tests/unit/SchemaField.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import useSchemaForm from '../../src/features/useSchemaForm'
import SchemaField from '../../src/SchemaField.vue'
import { UPDATE_FORM_MODEL, SCHEMA_MODEL_PATH } from '../../src/utils/constants'
import { UPDATE_FORM_MODEL, SCHEMA_MODEL_PATH, INJECTED_LOCAL_COMPONENTS } from '../../src/utils/constants'

import { mount } from '@vue/test-utils'
import { ref, provide } from 'vue'
Expand All @@ -16,7 +16,11 @@ const updateFormModel = jest.fn()
const SchemaFieldWrapper = (
binds,
formModel = null,
{ mockUpdate = false, path = '' } = {}
{
mockUpdate = false,
path = '',
injectedLocalComponents = null
} = {}
) => {
return {
components: { SchemaField },
Expand All @@ -38,6 +42,11 @@ const SchemaFieldWrapper = (
provide(SCHEMA_MODEL_PATH, path)
}

if (injectedLocalComponents) {
// Usually provided by SchemaFormFactory
provide(INJECTED_LOCAL_COMPONENTS, injectedLocalComponents)
}

return {
binds
}
Expand Down Expand Up @@ -86,6 +95,24 @@ describe('SchemaField', () => {
)
})

it('uses the injected local components if available', () => {
const FormText = { name: 'LocalFormText' }

const wrapper = mount(
SchemaFieldWrapper(
{
field: {
model: 'firstName',
component: 'FormText'
}
}, null,
{ injectedLocalComponents: { FormText } }
)
)

expect(wrapper.findComponent({ name: 'LocalFormText' }).exists()).toBe(true)
})

describe('binding v-model', () => {
it('binds the correct value from the provided form model', () => {
const model = ref({
Expand Down
33 changes: 33 additions & 0 deletions packages/formvuelate/tests/unit/SchemaFormFactory.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { inject, h } from 'vue'
import SchemaFormFactory from '../../src/SchemaFormFactory'
import SchemaForm from '../../src/SchemaForm.vue'
import { INJECTED_LOCAL_COMPONENTS } from '../../src/utils/constants'
import { mount } from '@vue/test-utils'

const props = {
schema: {}
Expand Down Expand Up @@ -81,4 +84,34 @@ describe('SchemaFormFactory', () => {
expect.objectContaining({ FormText, FormSelect })
)
})

it('provides the local components to sub FVL components', () => {
const factory = SchemaFormFactory([], {
FormText, FormSelect
})

const injecting = {
setup () {
const locals = inject(INJECTED_LOCAL_COMPONENTS)

return {
locals
}
}
}

const wrapper = mount({
components: { injecting },
setup () {
factory.setup(props, context)

return () => h(injecting)
}
})

expect(wrapper.findComponent(injecting).vm.locals).toEqual({
FormText,
FormSelect
})
})
})

0 comments on commit 34fad96

Please sign in to comment.