dynamic recusive form
This commit is contained in:
parent
f49153603a
commit
bf6dc2c944
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
18
package-lock.json
generated
18
package-lock.json
generated
@ -6902,15 +6902,6 @@
|
|||||||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
|
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"string_decoder": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
|
||||||
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"safe-buffer": "5.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||||
@ -6944,6 +6935,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
|
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "5.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"stringstream": {
|
"stringstream": {
|
||||||
"version": "0.0.5",
|
"version": "0.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
<!--
|
||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="submit()">
|
<form @submit.prevent="submit()">
|
||||||
<div v-for="(el, idx) in elements" :key="idx">
|
<div v-for="(el, idx) in elements" :key="idx">
|
||||||
@ -19,10 +20,77 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
-->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import MyInput from 'components/my-input.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MyForm",
|
name: "MyForm",
|
||||||
|
render(createElement) {
|
||||||
|
let self = this;
|
||||||
|
let _cElCall;
|
||||||
|
_cElCall = function(elements, formData) {
|
||||||
|
let formEl = [ ];
|
||||||
|
elements.forEach(el => {
|
||||||
|
let n = el.name ? el.name : el.key;
|
||||||
|
switch (el.element) {
|
||||||
|
case "my-input":
|
||||||
|
formEl.push(createElement(MyInput, {
|
||||||
|
props: {
|
||||||
|
name: n,
|
||||||
|
label: el.label,
|
||||||
|
description: el.description,
|
||||||
|
props: el.props,
|
||||||
|
value: formData[n],
|
||||||
|
validate: el.validate
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
input(val) {
|
||||||
|
formData[n] = val;
|
||||||
|
},
|
||||||
|
validate(valid) {
|
||||||
|
el.valid = valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
break;
|
||||||
|
case "section":
|
||||||
|
formEl.push(createElement("h3", el.label));
|
||||||
|
if (!formData[n]) {
|
||||||
|
formData[n] = { };
|
||||||
|
}
|
||||||
|
formEl.push(createElement("div", _cElCall(el.subElements, formData[n])));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return formEl;
|
||||||
|
}
|
||||||
|
|
||||||
|
let formElements = _cElCall(this.elements, self.formData);
|
||||||
|
this.buttons.forEach(b => {
|
||||||
|
formElements.push(createElement("button", {
|
||||||
|
class: {
|
||||||
|
button: true
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
click(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
self.buttonClick(b.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, b.label ? b.label : "OK"))
|
||||||
|
})
|
||||||
|
|
||||||
|
return createElement('form', {
|
||||||
|
on: {
|
||||||
|
submit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, formElements)
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
initData: {
|
initData: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -52,29 +120,29 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
formData: this.initData,
|
formData: this.initData,
|
||||||
formErrors: {},
|
// formErrors: {},
|
||||||
elementsMap: {}
|
// elementsMap: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
/*created() {
|
||||||
this.setOrder();
|
this.setOrder();
|
||||||
},
|
},*/
|
||||||
watch: {
|
watch: {
|
||||||
elements() {
|
/*elements() {
|
||||||
this.setOrder();
|
this.setOrder();
|
||||||
},
|
},*/
|
||||||
initData() {
|
initData() {
|
||||||
this.formData = this.initData;
|
this.formData = this.initData;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setOrder() {
|
/*setOrder() {
|
||||||
this.elementsMap = {};
|
this.elementsMap = {};
|
||||||
for (let a in this.elements) {
|
for (let a in this.elements) {
|
||||||
this.elementsMap[this.elements[a].key] = this.elements[a];
|
this.elementsMap[this.elements[a].key] = this.elements[a];
|
||||||
}
|
}
|
||||||
},
|
},*/
|
||||||
validateData(name) {
|
/*validateData(name) {
|
||||||
if (this.elementsMap[name].required) {
|
if (this.elementsMap[name].required) {
|
||||||
if (!this.formData[name]) {
|
if (!this.formData[name]) {
|
||||||
this.$set(this.formErrors, name, {
|
this.$set(this.formErrors, name, {
|
||||||
@ -88,6 +156,17 @@ export default {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
validateElement(el, val) {
|
||||||
|
if (el.validate) {
|
||||||
|
let v = el.validate;
|
||||||
|
if (v.required && !val) {
|
||||||
|
el.validatorMessage = v.requiredMessage ? v.requiredMessage : "input is required";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},*/
|
||||||
buttonClick(type) {
|
buttonClick(type) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case 'submit':
|
case 'submit':
|
||||||
@ -96,6 +175,32 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
submit() {
|
submit() {
|
||||||
|
// bad hacky solution, but works
|
||||||
|
this.$children.forEach(c => {
|
||||||
|
c.validateValue();
|
||||||
|
});
|
||||||
|
|
||||||
|
let _validateE;
|
||||||
|
_validateE = function(eArr) {
|
||||||
|
for (let i = 0; i< eArr.length; ++i) {
|
||||||
|
if (eArr[i].valid === false) {
|
||||||
|
return false;
|
||||||
|
} else if (eArr[i].subElements) {
|
||||||
|
// validate subElements
|
||||||
|
let subValid = _validateE(eArr[i].subElements);
|
||||||
|
if (!subValid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_validateE(this.elements)) {
|
||||||
|
this.submitHandler(this.formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
let valid = true;
|
let valid = true;
|
||||||
Object.keys(this.elementsMap).forEach(key => {
|
Object.keys(this.elementsMap).forEach(key => {
|
||||||
valid = (this.validateData(key) && valid);
|
valid = (this.validateData(key) && valid);
|
||||||
@ -103,6 +208,7 @@ export default {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
this.submitHandler(this.formData);
|
this.submitHandler(this.formData);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,22 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
<input type="number" v-if="props && props.type == 'number'"
|
||||||
|
v-model="currentValue"
|
||||||
|
:class="{invalid}"
|
||||||
|
:id="name"
|
||||||
|
:name="name"
|
||||||
|
:placeholder="props.placeholder"
|
||||||
|
@blur="validateValue"
|
||||||
|
@change="handleChange"
|
||||||
|
>
|
||||||
<input type="text" v-if="props && props.type == 'text'"
|
<input type="text" v-if="props && props.type == 'text'"
|
||||||
v-model="currentValue"
|
v-model="currentValue"
|
||||||
:class="{invalid}"
|
:class="{invalid}"
|
||||||
:id="name"
|
:id="name"
|
||||||
:name="name"
|
:name="name"
|
||||||
:placeholder="props.placeholder"
|
:placeholder="props.placeholder"
|
||||||
@blur="validate"
|
@blur="validateValue"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<input type="password" v-else-if="props && props.type == 'password'"
|
<input type="password" v-else-if="props && props.type == 'password'"
|
||||||
@ -21,7 +30,7 @@
|
|||||||
:id="name"
|
:id="name"
|
||||||
:name="name"
|
:name="name"
|
||||||
:placeholder="props.placeholder"
|
:placeholder="props.placeholder"
|
||||||
@blur="validate"
|
@blur="validateValue"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<div class="checkbox_holder" v-else-if="props && props.type == 'checkbox'">
|
<div class="checkbox_holder" v-else-if="props && props.type == 'checkbox'">
|
||||||
@ -30,6 +39,7 @@
|
|||||||
v-model="currentValue"
|
v-model="currentValue"
|
||||||
:id="name"
|
:id="name"
|
||||||
:name="name"
|
:name="name"
|
||||||
|
@blur="validateValue"
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<div class="check_checkbox"></div>
|
<div class="check_checkbox"></div>
|
||||||
@ -54,17 +64,29 @@ export default {
|
|||||||
'name',
|
'name',
|
||||||
'props',
|
'props',
|
||||||
'value',
|
'value',
|
||||||
'invalid',
|
// 'invalid',
|
||||||
'validatorMessage'
|
// 'validatorMessage',
|
||||||
|
'validate'
|
||||||
],
|
],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentValue: this.value
|
currentValue: this.value,
|
||||||
|
invalid: false,
|
||||||
|
validatorMessage: ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
validate() {
|
validateValue() {
|
||||||
this.$emit('validate', this.currentValue);
|
var valid = true;
|
||||||
|
let v = this.validate;
|
||||||
|
if (v) {
|
||||||
|
if (v.required && !this.currentValue) {
|
||||||
|
valid = false;
|
||||||
|
this.validatorMessage = (typeof v.requiredMessage == "string") ? v.requiredMessage : "input required";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.invalid = !valid;
|
||||||
|
this.$emit('validate', valid);
|
||||||
},
|
},
|
||||||
handleChange() {
|
handleChange() {
|
||||||
this.$emit('change', this.currentValue);
|
this.$emit('change', this.currentValue);
|
||||||
@ -72,6 +94,30 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
currentValue(val) {
|
currentValue(val) {
|
||||||
|
if (this.props && this.props.datatype) {
|
||||||
|
// convert
|
||||||
|
let t = this.props.datatype;
|
||||||
|
let newVal;
|
||||||
|
switch (t) {
|
||||||
|
case "int":
|
||||||
|
newVal = parseInt(this.currentValue);
|
||||||
|
if (isNaN(newVal)) {
|
||||||
|
newVal = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "float":
|
||||||
|
newVal = parseFloat(this.currentValue);
|
||||||
|
if (isNaN(newVal)) {
|
||||||
|
newVal = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newVal !== this.currentValue) {
|
||||||
|
this.currentValue = newVal;
|
||||||
|
return; // prevent double input events
|
||||||
|
}
|
||||||
|
}
|
||||||
this.$emit('input', val);
|
this.$emit('input', val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,10 @@ export default {
|
|||||||
key: "username",
|
key: "username",
|
||||||
element: "my-input",
|
element: "my-input",
|
||||||
icon: "icon-user",
|
icon: "icon-user",
|
||||||
required: true,
|
validate: {
|
||||||
requiredMessage: "Der Benutzername wird benötigt!",
|
required: true,
|
||||||
|
requiredMessage: "Der Benutzername wird benötigt!"
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
type: "text",
|
type: "text",
|
||||||
placeholder: "Benutzername"
|
placeholder: "Benutzername"
|
||||||
@ -39,8 +41,10 @@ export default {
|
|||||||
key: "password",
|
key: "password",
|
||||||
element: "my-input",
|
element: "my-input",
|
||||||
icon: "icon-key",
|
icon: "icon-key",
|
||||||
required: true,
|
validate: {
|
||||||
requiredMessage: "Das Passwort wird benötigt!",
|
required: true,
|
||||||
|
requiredMessage: "Das Passwort wird benötigt!"
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
type: "password",
|
type: "password",
|
||||||
placeholder: "Passwort"
|
placeholder: "Passwort"
|
||||||
|
Loading…
Reference in New Issue
Block a user