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=",
|
||||
"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": {
|
||||
"version": "2.1.1",
|
||||
"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": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||
|
@ -1,3 +1,4 @@
|
||||
<!--
|
||||
<template>
|
||||
<form @submit.prevent="submit()">
|
||||
<div v-for="(el, idx) in elements" :key="idx">
|
||||
@ -19,10 +20,77 @@
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
-->
|
||||
|
||||
<script>
|
||||
import MyInput from 'components/my-input.vue';
|
||||
|
||||
export default {
|
||||
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: {
|
||||
initData: {
|
||||
type: Object,
|
||||
@ -52,29 +120,29 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
formData: this.initData,
|
||||
formErrors: {},
|
||||
elementsMap: {}
|
||||
// formErrors: {},
|
||||
// elementsMap: {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
/*created() {
|
||||
this.setOrder();
|
||||
},
|
||||
},*/
|
||||
watch: {
|
||||
elements() {
|
||||
/*elements() {
|
||||
this.setOrder();
|
||||
},
|
||||
},*/
|
||||
initData() {
|
||||
this.formData = this.initData;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setOrder() {
|
||||
/*setOrder() {
|
||||
this.elementsMap = {};
|
||||
for (let a in this.elements) {
|
||||
this.elementsMap[this.elements[a].key] = this.elements[a];
|
||||
}
|
||||
},
|
||||
validateData(name) {
|
||||
},*/
|
||||
/*validateData(name) {
|
||||
if (this.elementsMap[name].required) {
|
||||
if (!this.formData[name]) {
|
||||
this.$set(this.formErrors, name, {
|
||||
@ -88,6 +156,17 @@ export default {
|
||||
}
|
||||
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) {
|
||||
switch(type) {
|
||||
case 'submit':
|
||||
@ -96,6 +175,32 @@ export default {
|
||||
}
|
||||
},
|
||||
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;
|
||||
Object.keys(this.elementsMap).forEach(key => {
|
||||
valid = (this.validateData(key) && valid);
|
||||
@ -103,6 +208,7 @@ export default {
|
||||
if (valid) {
|
||||
this.submitHandler(this.formData);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,22 @@
|
||||
</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'"
|
||||
v-model="currentValue"
|
||||
:class="{invalid}"
|
||||
:id="name"
|
||||
:name="name"
|
||||
:placeholder="props.placeholder"
|
||||
@blur="validate"
|
||||
@blur="validateValue"
|
||||
@change="handleChange"
|
||||
>
|
||||
<input type="password" v-else-if="props && props.type == 'password'"
|
||||
@ -21,7 +30,7 @@
|
||||
:id="name"
|
||||
:name="name"
|
||||
:placeholder="props.placeholder"
|
||||
@blur="validate"
|
||||
@blur="validateValue"
|
||||
@change="handleChange"
|
||||
>
|
||||
<div class="checkbox_holder" v-else-if="props && props.type == 'checkbox'">
|
||||
@ -30,6 +39,7 @@
|
||||
v-model="currentValue"
|
||||
:id="name"
|
||||
:name="name"
|
||||
@blur="validateValue"
|
||||
@change="handleChange"
|
||||
>
|
||||
<div class="check_checkbox"></div>
|
||||
@ -54,17 +64,29 @@ export default {
|
||||
'name',
|
||||
'props',
|
||||
'value',
|
||||
'invalid',
|
||||
'validatorMessage'
|
||||
// 'invalid',
|
||||
// 'validatorMessage',
|
||||
'validate'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value
|
||||
currentValue: this.value,
|
||||
invalid: false,
|
||||
validatorMessage: ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
validate() {
|
||||
this.$emit('validate', this.currentValue);
|
||||
validateValue() {
|
||||
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() {
|
||||
this.$emit('change', this.currentValue);
|
||||
@ -72,6 +94,30 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,10 @@ export default {
|
||||
key: "username",
|
||||
element: "my-input",
|
||||
icon: "icon-user",
|
||||
required: true,
|
||||
requiredMessage: "Der Benutzername wird benötigt!",
|
||||
validate: {
|
||||
required: true,
|
||||
requiredMessage: "Der Benutzername wird benötigt!"
|
||||
},
|
||||
props: {
|
||||
type: "text",
|
||||
placeholder: "Benutzername"
|
||||
@ -39,8 +41,10 @@ export default {
|
||||
key: "password",
|
||||
element: "my-input",
|
||||
icon: "icon-key",
|
||||
required: true,
|
||||
requiredMessage: "Das Passwort wird benötigt!",
|
||||
validate: {
|
||||
required: true,
|
||||
requiredMessage: "Das Passwort wird benötigt!"
|
||||
},
|
||||
props: {
|
||||
type: "password",
|
||||
placeholder: "Passwort"
|
||||
|
Loading…
Reference in New Issue
Block a user