1
0
mirror of synced 2025-02-19 22:03:16 +03:00

Adds initial grouping capability

This commit is contained in:
Justin Schroeder 2020-04-18 00:39:25 -04:00
parent dfef74cd27
commit 105cae1a78
11 changed files with 2003 additions and 3314 deletions

View File

@ -7,12 +7,14 @@
help="Fields can be grouped" help="Fields can be grouped"
> >
<FormulateInput <FormulateInput
label="First and last name"
name="Name" name="Name"
type="text" type="text"
placeholder="Users name" placeholder="Users name"
/> />
<FormulateInput <FormulateInput
name="Email" name="Email"
label="Email address"
type="email" type="email"
placeholder="Users email" placeholder="Users email"
validation="required|email" validation="required|email"

5222
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -7,12 +7,13 @@ import isPlainObject from 'is-plain-object'
import { en } from '@braid/vue-formulate-i18n' import { en } from '@braid/vue-formulate-i18n'
import fauxUploader from './libs/faux-uploader' import fauxUploader from './libs/faux-uploader'
import FormulateSlot from './FormulateSlot' import FormulateSlot from './FormulateSlot'
import FormulateInput from './FormulateInput.vue'
import FormulateForm from './FormulateForm.vue' import FormulateForm from './FormulateForm.vue'
import FormulateInput from './FormulateInput.vue'
import FormulateErrors from './FormulateErrors.vue' import FormulateErrors from './FormulateErrors.vue'
import FormulateHelp from './slots/FormulateHelp.vue' import FormulateHelp from './slots/FormulateHelp.vue'
import FormulateGrouping from './FormulateGrouping.vue' import FormulateGrouping from './FormulateGrouping.vue'
import FormulateLabel from './slots/FormulateLabel.vue' import FormulateLabel from './slots/FormulateLabel.vue'
import FormulateAddMore from './slots/FormulateAddMore.vue'
import FormulateInputBox from './inputs/FormulateInputBox.vue' import FormulateInputBox from './inputs/FormulateInputBox.vue'
import FormulateInputText from './inputs/FormulateInputText.vue' import FormulateInputText from './inputs/FormulateInputText.vue'
import FormulateInputFile from './inputs/FormulateInputFile.vue' import FormulateInputFile from './inputs/FormulateInputFile.vue'
@ -40,6 +41,7 @@ class Formulate {
FormulateLabel, FormulateLabel,
FormulateInput, FormulateInput,
FormulateErrors, FormulateErrors,
FormulateAddMore,
FormulateGrouping, FormulateGrouping,
FormulateInputBox, FormulateInputBox,
FormulateInputText, FormulateInputText,
@ -54,7 +56,10 @@ class Formulate {
slotDefaults: { slotDefaults: {
label: 'FormulateLabel', label: 'FormulateLabel',
help: 'FormulateHelp', help: 'FormulateHelp',
errors: 'FormulateErrors' errors: 'FormulateErrors',
grouping: 'FormulateGrouping',
repeatable: 'FormulateRepeatable',
addMore: 'FormulateAddMore'
}, },
library, library,
rules, rules,
@ -160,8 +165,8 @@ class Formulate {
*/ */
slotComponent (type, slot) { slotComponent (type, slot) {
const def = this.options.library[type] const def = this.options.library[type]
if (def.slots && def.slots[slot]) { if (def.slotComponents && def.slotComponents[slot]) {
return def.slots[slot] return def.slotComponents[slot]
} }
return this.options.slotDefaults[slot] return this.options.slotDefaults[slot]
} }

View File

@ -1,13 +1,24 @@
<template> <template>
<FormulateSlot <FormulateSlot
name="repeatable" name="grouping"
:context="context"
> >
<FormulateRepeatable <component
v-for="item in items" :is="context.slotComponents.repeatable"
:key="item.id" v-for="(item, index) in items"
:key="index"
> >
<slot /> <slot />
</FormulateRepeatable> </component>
<FormulateSlot
v-if="canAddMore"
name="addmore"
>
<component
:is="context.slotComponents.addMore"
@add="addItem"
/>
</FormulateSlot>
</FormulateSlot> </FormulateSlot>
</template> </template>
@ -20,8 +31,21 @@ export default {
} }
}, },
computed: { computed: {
canAddMore () {
return (this.context.repeatable && this.items.length < this.context.limit)
},
items () { items () {
return [{ id: 1 }, { id: 2 }] return Array.isArray(this.context.model) ? this.context.model : []
}
},
methods: {
addItem () {
const item = { id: this.items.length }
if (Array.isArray(this.context.model)) {
this.context.model.push(item)
return
}
this.context.model = [item]
} }
} }
} }

View File

@ -122,6 +122,10 @@ export default {
type: [String, Boolean], type: [String, Boolean],
default: false default: false
}, },
limit: {
type: Number,
default: Infinity
},
help: { help: {
type: [String, Boolean], type: [String, Boolean],
default: false default: false
@ -134,6 +138,10 @@ export default {
type: [String, Array, Boolean], type: [String, Array, Boolean],
default: false default: false
}, },
repeatable: {
type: Boolean,
default: true
},
validation: { validation: {
type: [String, Boolean, Array], type: [String, Boolean, Array],
default: false default: false

View File

@ -7,7 +7,7 @@ export default {
p = p.$parent p = p.$parent
} }
if (p.$scopedSlots && p.$scopedSlots[props.name]) { if (p.$scopedSlots && p.$scopedSlots[props.name]) {
return p.$scopedSlots[props.name](props) return p.$scopedSlots[props.name](props.context || props)
} }
return h('div', data, children) return h('div', data, children)
} }

View File

@ -1,4 +1,3 @@
import nanoid from 'nanoid/non-secure'
import { map, arrayify, shallowEqualObjects } from './utils' import { map, arrayify, shallowEqualObjects } from './utils'
/** /**
@ -23,9 +22,11 @@ export default {
imageBehavior: this.imageBehavior, imageBehavior: this.imageBehavior,
label: this.label, label: this.label,
labelPosition: this.logicalLabelPosition, labelPosition: this.logicalLabelPosition,
limit: this.limit,
name: this.nameOrFallback, name: this.nameOrFallback,
performValidation: this.performValidation.bind(this), performValidation: this.performValidation.bind(this),
preventWindowDrops: this.preventWindowDrops, preventWindowDrops: this.preventWindowDrops,
repeatable: this.repeatable,
setErrors: this.setErrors.bind(this), setErrors: this.setErrors.bind(this),
showValidationErrors: this.showValidationErrors, showValidationErrors: this.showValidationErrors,
slotComponents: this.slotComponents, slotComponents: this.slotComponents,
@ -238,7 +239,10 @@ function slotComponents () {
return { return {
label: this.$formulate.slotComponent(this.type, 'label'), label: this.$formulate.slotComponent(this.type, 'label'),
help: this.$formulate.slotComponent(this.type, 'help'), help: this.$formulate.slotComponent(this.type, 'help'),
errors: this.$formulate.slotComponent(this.type, 'errors') errors: this.$formulate.slotComponent(this.type, 'errors'),
grouping: this.$formulate.slotComponent(this.type, 'grouping'),
repeatable: this.$formulate.slotComponent(this.type, 'repeatable'),
addMore: this.$formulate.slotComponent(this.type, 'addMore')
} }
} }

View File

@ -0,0 +1,13 @@
<template>
<div class="formulate-input-group-add-more">
<button @click="$emit('add')">
Add more
</button>
</div>
</template>
<script>
export default {
}
</script>

View File

@ -1,6 +1,6 @@
<template> <template>
<div <div
class="formulate-group-row" class="formulate-input-group-item"
> >
<FormulateSlot <FormulateSlot
name="default" name="default"

View File

@ -68,6 +68,7 @@ describe('Formulate', () => {
'FormulateLabel', 'FormulateLabel',
'FormulateInput', 'FormulateInput',
'FormulateErrors', 'FormulateErrors',
'FormulateAddMore',
'FormulateGrouping', 'FormulateGrouping',
'FormulateInputBox', 'FormulateInputBox',
'FormulateInputText', 'FormulateInputText',

View File

@ -42,7 +42,15 @@
} }
.formulate-input-group-item { .formulate-input-group-item {
margin-bottom: .5em; padding-bottom: 1.5em;
margin-bottom: 1.5em;
border-bottom: 1px solid $formulate-gray;
&:last-child {
margin-bottom: 1.5em;
border-bottom: 0;
padding-bottom: 0;
}
} }
&:last-child { &:last-child {