Added strict one-way binding to all form components

This commit is contained in:
Joel Collins 2019-06-14 15:35:08 +01:00
parent 4a0351f80c
commit 5e69e52bcd
8 changed files with 181 additions and 33 deletions

View file

@ -94,15 +94,10 @@ export default {
}, },
{ {
fieldType: "textInput", fieldType: "textInput",
placeholder: "First Name", placeholder: "Name",
label: "First Name", label: "Name",
name: "firstName" name: "name",
}, value: "Squidward"
{
fieldType: "textInput",
placeholder: "Last Name",
label: "Last Name",
name: "lastName"
}, },
{ {
fieldType: "numberInput", fieldType: "numberInput",
@ -110,7 +105,35 @@ export default {
name: "age", name: "age",
label: "Age", label: "Age",
minValue: 0 minValue: 0
} },
[
{
fieldType: "numberInput",
placeholder: "Number",
name: "leftnum",
label: "Left"
},
{
fieldType: "numberInput",
placeholder: "Number",
name: "rightnum",
label: "Right"
}
],
{
fieldType: "radioList",
name: "coolness",
label: "Coolness",
options: ["None", "Some", "Very"],
value: "Some"
},
{
fieldType: "checkList",
name: "ingredients",
label: "Ingredients",
options: ["Pork", "Pie"],
value: ["Pork"]
},
] ]
} }
] ]

View file

@ -1,12 +1,24 @@
<template> <template>
<div> <div class="uk-form-stacked">
<component v-for="(field, index) in schema" <div v-for="(field, index) in schema" :key="index">
:key="index"
:is="field.fieldType" <div v-if="Array.isArray(field)" class="uk-grid-small" uk-grid>
v-model="formData[field.name]" <div v-for="(subfield, subindex) in field" :key="subindex" class="uk-width-expand">
v-bind="field"> <component
:is="subfield.fieldType"
@input="updateForm(subfield.name, $event)"
v-bind="subfield">
</component>
</div>
</div>
<component
:is="field.fieldType"
@input="updateForm(field.name, $event)"
v-bind="field">
</component>
</component> </div>
</div> </div>
</template> </template>
@ -16,6 +28,8 @@ import numberInput from "./fieldComponents/numberInput";
import selectList from "./fieldComponents/selectList"; import selectList from "./fieldComponents/selectList";
import textInput from "./fieldComponents/textInput"; import textInput from "./fieldComponents/textInput";
import htmlBlock from "./fieldComponents/htmlBlock"; import htmlBlock from "./fieldComponents/htmlBlock";
import radioList from "./fieldComponents/radioList";
import checkList from "./fieldComponents/checkList"
export default { export default {
name: 'JsonForm', name: 'JsonForm',
@ -24,7 +38,9 @@ export default {
numberInput, numberInput,
selectList, selectList,
textInput, textInput,
htmlBlock htmlBlock,
radioList,
checkList
}, },
props: { props: {
@ -43,8 +59,24 @@ export default {
created: function () { created: function () {
// `this` points to the vm instance // `this` points to the vm instance
console.log(this.schema) console.log(this.schema)
},
methods: {
updateForm(fieldName, value) {
console.log(`${fieldName}: ${value}`)
this.$set(this.formData, fieldName, value);
this.$emit('input', this.formData)
}
} }
} }
</script> </script>
<style scoped></style> <style scoped>
.flex-container {
display: flex;
}
.flex-container > div {
flex-basis: 100%
}
</style>

View file

@ -0,0 +1,47 @@
<template>
<div>
<label>{{label}}</label>
<div class="uk-form-controls">
<div v-for="option in options" :key="option">
<label><input class="uk-checkbox" type="checkbox" v-bind:value="option" v-model="computedChecked"> {{ option }}</label>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'checkList',
props: [
'options',
'name',
'label',
'value'
],
data: function () {
return {
itemsChecked: this.value || []
}
},
computed: {
computedChecked: {
get() {
return this.itemsChecked
},
set(val) {
this.itemsChecked = val
this.$emit('input', this.itemsChecked)
}
}
}
}
</script>
<style scoped></style>

View file

@ -7,6 +7,7 @@
<script> <script>
export default { export default {
name: 'textInput', name: 'textInput',
props: [ props: [
'label', 'label',
'name', 'name',

View file

@ -1,8 +1,9 @@
<template> <template>
<div> <div>
<label>{{label}}</label> <label class="uk-form-label">{{label}}</label>
<input <input
class="uk-input uk-form-small"
type="number" type="number"
:name="name" :name="name"
:value="value" :value="value"
@ -17,7 +18,16 @@
export default { export default {
name: 'numberInput', name: 'numberInput',
props: ['placeholder', 'label', 'name', 'value']
props: [
'placeholder',
'label',
'name',
'value'
]
} }
</script> </script>
<style scoped></style>

View file

@ -0,0 +1,29 @@
<template>
<div>
<label>{{label}}</label>
<div class="uk-form-controls">
<div v-for="option in options" :key="option">
<label><input class="uk-radio" type="radio" :name="name" :value="option" :checked="value==option" @input="$emit('input', $event.target.value)"> {{ option }}</label>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'radioList',
props: [
'options',
'name',
'label',
'value'
]
}
</script>
<style scoped></style>

View file

@ -1,14 +1,17 @@
<template> <template>
<div> <div>
<label>{{label}}</label> <label class="uk-form-label">{{label}}</label>
<select :multiple="multi"
:value="value" <select
@input="$emit('input', class="uk-select uk-form-small"
$event.target.value)"> :multiple="multi"
<option v-for="option in options" :value="value"
:key="option"> @input="$emit('input', $event.target.value)"
>
<option v-for="option in options" :key="option">
{{option}} {{option}}
</option> </option>
</select> </select>
</div> </div>
</template> </template>
@ -16,6 +19,7 @@
<script> <script>
export default { export default {
name: 'selectList', name: 'selectList',
props: [ props: [
'multi', 'multi',
'options', 'options',

View file

@ -1,13 +1,14 @@
<template> <template>
<div> <div>
<label>{{label}}</label> <label class="uk-form-label">{{label}}</label>
<input <input
class="uk-input uk-form-small"
type="text" type="text"
:name="name" v-bind:name="name"
:value="value" v-bind:value="value"
v-bind:placeholder="placeholder"
@input="$emit('input',$event.target.value)" @input="$emit('input',$event.target.value)"
:placeholder="placeholder"
> >
</div> </div>
@ -16,6 +17,7 @@
<script> <script>
export default { export default {
name: 'textInput', name: 'textInput',
props: [ props: [
'placeholder', 'placeholder',
'label', 'label',