1
0
mirror of synced 2024-12-01 17:46:07 +03:00
vue-formulario/src/components/FormulateElement.vue
Justin Schroeder c5e90171e6 New Feature: FormulateElement now supports help text via the new GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
These shell commands are defined internally.  Type `help' to see this list.
Type `help name' to find out more about the function `name'.
Use `info bash' to find out more about the shell in general.
Use `man -k' or `info' to find out more about commands not in this list.

A star (*) next to a name means that the command is disabled.

 JOB_SPEC [&]                       (( expression ))
 . filename [arguments]             :
 [ arg... ]                         [[ expression ]]
 alias [-p] [name[=value] ... ]     bg [job_spec ...]
 bind [-lpvsPVS] [-m keymap] [-f fi break [n]
 builtin [shell-builtin [arg ...]]  caller [EXPR]
 case WORD in [PATTERN [| PATTERN]. cd [-L|-P] [dir]
 command [-pVv] command [arg ...]   compgen [-abcdefgjksuv] [-o option
 complete [-abcdefgjksuv] [-pr] [-o continue [n]
 declare [-afFirtx] [-p] [name[=val dirs [-clpv] [+N] [-N]
 disown [-h] [-ar] [jobspec ...]    echo [-neE] [arg ...]
 enable [-pnds] [-a] [-f filename]  eval [arg ...]
 exec [-cl] [-a name] file [redirec exit [n]
 export [-nf] [name[=value] ...] or false
 fc [-e ename] [-nlr] [first] [last fg [job_spec]
 for NAME [in WORDS ... ;] do COMMA for (( exp1; exp2; exp3 )); do COM
 function NAME { COMMANDS ; } or NA getopts optstring name [arg]
 hash [-lr] [-p pathname] [-dt] [na help [-s] [pattern ...]
 history [-c] [-d offset] [n] or hi if COMMANDS; then COMMANDS; [ elif
 jobs [-lnprs] [jobspec ...] or job kill [-s sigspec | -n signum | -si
 let arg [arg ...]                  local name[=value] ...
 logout                             popd [+N | -N] [-n]
 printf [-v var] format [arguments] pushd [dir | +N | -N] [-n]
 pwd [-LP]                          read [-ers] [-u fd] [-t timeout] [
 readonly [-af] [name[=value] ...]  return [n]
 select NAME [in WORDS ... ;] do CO set [--abefhkmnptuvxBCHP] [-o opti
 shift [n]                          shopt [-pqsu] [-o long-option] opt
 source filename [arguments]        suspend [-f]
 test [expr]                        time [-p] PIPELINE
 times                              trap [-lp] [arg signal_spec ...]
 true                               type [-afptP] name [name ...]
 typeset [-afFirtx] [-p] name[=valu ulimit [-SHacdfilmnpqstuvx] [limit
 umask [-p] [-S] [mode]             unalias [-a] name [name ...]
 unset [-f] [-v] [name ...]         until COMMANDS; do COMMANDS; done
 variables - Some variable names an wait [n]
 while COMMANDS; do COMMANDS; done  { COMMANDS ; } prop
2018-05-18 14:46:04 -04:00

383 lines
9.7 KiB
Vue

<template>
<div :class="classes">
<div
class="formulate-element-input-wrapper"
:data-type="type"
:data-classification="classification"
:data-is-disabled="disabled"
>
<!-- TEXT STYLE INPUTS -->
<label
:for="id"
v-text="label"
v-if="label && (!isBoxInput || optionList.length > 1)"
/>
<input
ref="input"
:class="elementClasses"
:type="type"
:name="name"
v-model="val"
v-bind="attributes"
v-if="isTextInput"
@blur="errorBlurState = true"
:disabled="disabled"
>
<textarea
ref="textarea"
:class="elementClasses"
:type="type"
:name="name"
v-model="val"
v-bind="attributes"
v-if="isTextareaInput"
@blur="errorBlurState = true"
:disabled="disabled"
/>
<!-- BUTTON INPUTS -->
<button
:type="type"
:class="elementClasses"
v-if="isButtonInput"
:disabled="disabled || (type === 'submit' && (form.hasErrors && form.behavior === 'live'))"
>
<slot
v-if="$slots.button"
name="button"
/>
<span
v-text="label || name"
v-else
/>
</button>
<!-- SELECT INPUTS -->
<select
v-bind="attributes"
v-if="isSelectInput"
:class="elementClasses"
:name="name"
v-model="val"
@blur="errorBlurState = true"
:disabled="disabled"
>
<option
v-for="option in optionList"
:value="option.value"
:key="option.id"
v-bind="option.attributes || {}"
v-text="option.label"
/>
</select>
<!-- BOX INPUTS -->
<div
class="formulate-element-box-input-group"
v-if="isBoxInput"
>
<template v-for="option in optionList">
<input
type="radio"
:class="elementClasses"
:name="name"
:id="option.id"
:value="option.value"
:key="`${option.id}-input`"
v-bind="attributes"
v-model="val"
v-if="type === 'radio'"
@blur="errorBlurState = true"
:disabled="disabled"
>
<input
type="checkbox"
:class="elementClasses"
:name="name"
:id="option.id"
:value="option.value"
:key="`${option.id}-input`"
v-bind="attributes"
v-model="val"
v-if="type === 'checkbox'"
@blur="errorBlurState = true"
:disabled="disabled"
>
<label
:for="option.id"
:key="`${option.id}-label`"
v-text="option.label"
/>
</template>
</div>
<!-- CUSTOM SLOT INPUTS -->
<slot v-if="hasCustomInput" />
<!-- UNSUPORTED INPUT -->
<div
style="background-color: red; color: white"
v-if="isUnsupportedInput"
v-text="`Unsupported field type: ${type}.`"
/>
</div>
<div
class="formulate-help"
v-if="help"
v-text="help"
/>
<transition
name="formulate-errors"
>
<transition-group
tag="ul"
name="formulate-error-list"
class="formulate-errors"
v-if="shouldShowErrors && localAndValidationErrors.length"
>
<li
v-for="error in localAndValidationErrors"
v-text="error"
:key="error"
/>
</transition-group>
</transition>
</div>
</template>
<script>
import {inputTypes, equals, reduce, filter} from '../utils'
import shortid from 'shortid'
export default {
props: {
type: {
type: [String, Boolean],
default: 'text'
},
name: {
type: String,
required: true
},
initial: {
type: [String, Number, Boolean],
default: false
},
validation: {
type: [String, Boolean],
default: false
},
errors: {
type: Array,
default: () => []
},
label: {
type: [String, Boolean],
default: false
},
id: {
type: [String],
default: () => shortid.generate()
},
min: {
type: [String, Number, Boolean],
default: () => false
},
max: {
type: [String, Number, Boolean],
default: () => false
},
placeholder: {
type: [String, Number, Boolean],
default: () => false
},
options: {
type: [Object, Array],
default: () => []
},
multiple: {
type: Boolean,
default: false
},
showErrors: {
type: [Object, Boolean],
default: () => ({})
},
validationLabel: {
type: [String, Boolean],
default: false
},
elementClasses: {
type: [String, Array, Object],
default: () => {}
},
disabled: {
type: Boolean,
default: false
},
help: {
type: [Boolean, String],
default: false
}
},
data () {
return {
errorBlurState: false
}
},
computed: {
classification () {
if (this.isTextInput) return 'text'
if (this.isBoxInput) return 'box'
if (this.isButtonInput) return 'button'
if (this.isSelectInput) return 'select'
if (this.hasCustomInput) return 'custom'
return 'unsupported'
},
hasCustomInput () {
return (this.$slots.default && this.$slots.default.length)
},
isTextInput () {
return !this.hasCustomInput && inputTypes.text.includes(this.type)
},
isTextareaInput () {
return !this.hasCustomInput && inputTypes.textarea.includes(this.type)
},
isButtonInput () {
return !this.hasCustomInput && inputTypes.button.includes(this.type)
},
isSelectInput () {
return !this.hasCustomInput && inputTypes.select.includes(this.type)
},
isBoxInput () {
return !this.hasCustomInput && inputTypes.box.includes(this.type)
},
isUnsupportedInput () {
return (!this.hasCustomInput && !this.isTextInput && !this.isButtonInput && !this.isSelectInput && !this.isBoxInput && !this.isTextareaInput)
},
form () {
let parent = this.$parent
while (parent && parent.$data && parent.$data.parentIdentifier !== 'vue-formulate-wrapper-element') {
parent = parent.$parent
}
if (!parent.$data || parent.$data.parentIdentifier !== 'vue-formulate-wrapper-element') {
throw new Error('FormulateElement has no FormulateWrapper element')
}
return parent
},
values () {
return this.form.values
},
value () {
let value = this.values[this.name]
if (value === undefined) {
switch (this.type) {
case 'color':
return '#000000'
case 'checkbox':
if (this.optionList.length > 1) {
return []
}
break
}
}
return value
},
module () {
return this.form.$props['module']
},
formName () {
return this.form.$props['name']
},
classes () {
return {
'formulate-element': true,
[`formulate-element--type--${this.type}`]: true,
'formulate-element--has-value': !!this.value,
'formulate-element--has-errors': this.localAndValidationErrors.length && this.shouldShowErrors
}
},
validationErrors () {
return this.form.validationErrors[this.name] || []
},
storeErrors () {
return this.form.storeErrors[this.name] || []
},
formErrors () {
return this.form.errors[this.name] || []
},
localAndValidationErrors () {
return this.errors.concat(this.validationErrors).concat(this.formErrors)
},
shouldShowErrors () {
let show = this.form.shouldShowErrors
if (this.form.behavior === 'blur') {
show = show || this.errorBlurState
}
if (this.showErrors === false || this.showErrors === true) {
show = this.showErrors
}
return show
},
attributes () {
return ['min', 'max', 'placeholder', 'id', 'multiple']
.filter(prop => this[prop] !== false)
.reduce((attributes, attr) => {
attributes[attr] = this[attr]
return attributes
}, {})
},
optionList () {
if (!Array.isArray(this.options)) {
return reduce(this.options, (options, value, label) => options.concat({value, label, id: shortid.generate()}), [])
} else if (Array.isArray(this.options) && !this.options.length) {
return [{value: this.name, label: (this.label || this.name), id: shortid.generate()}]
}
return this.options
},
val: {
set (value) {
this.form.update({field: this.name, value})
if (this.isTextInput) {
this.$refs.input.value = value
}
},
get () {
return this.value
}
}
},
watch: {
localAndValidationErrors () {
if (!equals(this.localAndValidationErrors, this.storeErrors)) {
this.form.updateFieldErrors({
field: this.name,
errors: this.localAndValidationErrors
})
}
},
initial () {
this.form.update({field: this.name, value: this.initial})
}
},
created () {
if (typeof window === 'undefined') {
this.register()
}
},
mounted () {
this.register()
},
beforeDestroy () {
this.form.deregisterField(this.name)
},
methods: {
register () {
this.form.registerField(
this.name,
filter(this.$props, (prop, value) => ['name', 'type', 'id', 'label', 'validation', 'validationLabel'].includes(prop))
)
if (this.initial !== false) {
this.form.setInitial(this.name, this.initial)
}
}
}
}
</script>