Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6e773d0

Browse files
committedApr 27, 2016
Add files & first build
1 parent 15f3df5 commit 6e773d0

21 files changed

+42932
-6
lines changed
 

‎build/webpack.build.config.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@ var webpack = require("webpack");
22
var version = require("../package.json").version;
33
var banner = "/**\n" + " * vue-form-generator v" + version + "\n" + " * https://github.com/icebob/vue-form-generator\n" + " * Released under the MIT License.\n" + " */\n";
44

5+
var loaders = [
6+
{
7+
"test": /\.js?$/,
8+
"exclude": /node_modules/,
9+
"loader": "babel",
10+
"query": {
11+
"presets": [
12+
"es2015",
13+
"stage-0"
14+
],
15+
"plugins": []
16+
}
17+
},
18+
{
19+
"test": /\.vue?$/,
20+
"loader": "vue"
21+
}
22+
];
23+
524
module.exports = [
625

726
{
@@ -15,22 +34,28 @@ module.exports = [
1534
plugins: [
1635
new webpack.BannerPlugin(banner, {
1736
raw: true
18-
})]
37+
})],
38+
module: {
39+
loaders: loaders
40+
}
1941
},
2042

2143
{
2244
entry: "./src/index",
2345
output: {
2446
path: "./dist",
25-
filename: "vue-form-generator.js",
47+
filename: "vue-form-generator.min.js",
2648
library: "VueFormGenerator",
2749
libraryTarget: "umd"
2850
},
2951
plugins: [
3052
new webpack.optimize.UglifyJsPlugin,
3153
new webpack.BannerPlugin(banner, {
3254
raw: true
33-
})]
55+
})],
56+
module: {
57+
loaders: loaders
58+
}
3459
}
3560

3661
];

‎dist/vue-form-generator.js

Lines changed: 41951 additions & 0 deletions
Large diffs are not rendered by default.

‎dist/vue-form-generator.min.js

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "vue-form-generator",
33
"version": "0.1.0",
44
"description": "A schema-based form generator component for Vue.js",
5-
"main": "src/index.js",
5+
"main": "dist/vue-form-generator.js",
66
"scripts": {
77
"build": "webpack --config build/webpack.build.config.js",
88
"test": "webpack --config test/webpack.config.js"
@@ -18,7 +18,25 @@
1818
"author": "Icebob",
1919
"license": "MIT",
2020
"devDependencies": {
21-
"vue": "^1.0.21",
21+
"babel-core": "6.7.7",
22+
"babel-loader": "6.2.4",
23+
"babel-plugin-transform-runtime": "6.7.5",
24+
"babel-preset-es2015": "6.6.0",
25+
"babel-preset-stage-0": "6.5.0",
26+
"babel-runtime": "5.8.38",
27+
"css-loader": "0.23.1",
28+
"jade": "1.11.0",
29+
"jade-loader": "0.8.0",
30+
"lodash": "4.11.1",
31+
"moment": "2.13.0",
32+
"node-sass": "3.6.0",
33+
"sass-loader": "3.2.0",
34+
"style-loader": "0.13.1",
35+
"vue": "1.0.21",
36+
"vue-hot-reload-api": "1.3.2",
37+
"vue-html-loader": "1.2.2",
38+
"vue-loader": "8.2.3",
39+
"vue-style-loader": "1.0.0",
2240
"webpack": "1.13.0"
23-
}
41+
}
2442
}

‎src/fields/abstractField.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import {each, isFunction, isArray, isUndefined} from 'lodash';
2+
3+
export default {
4+
props: [
5+
"model",
6+
"schema",
7+
"disabled"
8+
],
9+
10+
computed: {
11+
value: {
12+
cache: false,
13+
get() {
14+
let val;
15+
if (isFunction(this.schema.get))
16+
val = this.schema.get(this.model);
17+
18+
else if (this.schema.model)
19+
val = this.$get("model." + this.schema.model);
20+
21+
if (isFunction(this.formatValueToField))
22+
val = this.formatValueToField(val);
23+
24+
return val;
25+
},
26+
27+
set(newValue) {
28+
29+
if (isFunction(this.formatValueToModel))
30+
newValue = this.formatValueToModel(newValue);
31+
32+
if (isFunction(this.schema.set))
33+
this.schema.set(this.model, newValue);
34+
35+
else if (this.schema.model)
36+
this.$set("model." + this.schema.model, newValue);
37+
}
38+
}
39+
},
40+
41+
watch: {
42+
value: function(newVal, oldVal) {
43+
//console.log("Value changed!");
44+
45+
if (isFunction(this.schema.onChanged)) {
46+
this.schema.onChanged(this.model, newVal, oldVal, this.schema);
47+
}
48+
49+
if (this.$parent.options.validateAfterChanged === true)
50+
this.validate();
51+
}
52+
},
53+
54+
methods: {
55+
validate() {
56+
this.clearValidationErrors();
57+
58+
if (this.schema.validator) {
59+
60+
let validators = [];
61+
if (!isArray(this.schema.validator)) {
62+
validators.push(this.schema.validator.bind(this));
63+
} else {
64+
each(this.schema.validator, (validator) => {
65+
validators.push(validator.bind(this));
66+
});
67+
}
68+
69+
each(validators, (validator) => {
70+
let err = validator(this.value, this.schema);
71+
if (err && err.length > 0) {
72+
Array.prototype.push.apply(this.schema.errors, err);
73+
// console.log(this.schema.errors);
74+
}
75+
});
76+
77+
}
78+
79+
if (isFunction(this.schema.onValidated)) {
80+
this.schema.onValidated(this.model, this.schema.errors, this.schema);
81+
}
82+
83+
return this.schema.errors;
84+
},
85+
86+
clearValidationErrors() {
87+
if (isUndefined(this.schema.errors))
88+
this.$set("schema.errors", []); // Be reactive
89+
else
90+
this.schema.errors.splice(0); // Clear
91+
}
92+
}
93+
}
94+

‎src/fields/fieldCheckbox.vue

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<template lang="jade">
2+
input(type="checkbox", :disabled="disabled", v-model="value")
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
8+
export default {
9+
mixins: [ abstractField ]
10+
}
11+
</script>

‎src/fields/fieldChecklist.vue

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<template lang="jade">
2+
.listbox.form-control(v-if="schema.listBox")
3+
.list-row(v-for="item in items")
4+
label
5+
input(type="checkbox", :checked="getItemIsChecked(item)", @change="onChanged($event, item)")
6+
| {{ getItemName(item) }}
7+
8+
.combobox.form-control(v-if="!schema.listBox")
9+
.mainRow(@click="onExpandCombo", :class="{ expanded: comboExpanded }")
10+
.info {{ selectedCount }} selected
11+
.arrow
12+
13+
.dropList()
14+
.list-row(v-if="comboExpanded", v-for="item in items")
15+
label
16+
input(type="checkbox", :checked="getItemIsChecked(item)", @change="onChanged($event, item)")
17+
| {{ getItemName(item) }}
18+
</template>
19+
20+
<script>
21+
import {isObject, isNil} from "lodash";
22+
import abstractField from './abstractField';
23+
24+
export default {
25+
mixins: [ abstractField ],
26+
27+
data() {
28+
return {
29+
comboExpanded: false
30+
}
31+
},
32+
33+
computed: {
34+
items() {
35+
let values = this.schema.values;
36+
if (typeof(values) == "function") {
37+
return values.apply(this, [this.model, this.schema]);
38+
} else
39+
return values;
40+
},
41+
42+
selectedCount() {
43+
if (this.value)
44+
return this.value.length;
45+
46+
return 0;
47+
}
48+
},
49+
50+
methods: {
51+
getItemID(item) {
52+
if (isObject(item) && item.id)
53+
return item.id;
54+
55+
return item;
56+
},
57+
58+
getItemName(item) {
59+
if (isObject(item) && item.name)
60+
return item.name;
61+
62+
return item;
63+
},
64+
65+
getItemIsChecked(item) {
66+
return (this.value && this.value.indexOf(this.getItemID(item)) != -1);
67+
},
68+
69+
onChanged(event, item) {
70+
if (isNil(this.value))
71+
this.value = [];
72+
73+
if (event.target.checked)
74+
this.value.push(this.getItemID(item));
75+
else
76+
this.value.$remove(this.getItemID(item));
77+
},
78+
79+
onExpandCombo(event) {
80+
this.comboExpanded = !this.comboExpanded;
81+
}
82+
}
83+
}
84+
</script>
85+
86+
87+
<style lang="sass" scoped>
88+
89+
.listbox, .dropList {
90+
height: auto;
91+
max-height: 150px;
92+
overflow: auto;
93+
94+
.list-row {
95+
label {
96+
font-weight: initial;
97+
}
98+
99+
input {
100+
margin-right: 0.3em;
101+
}
102+
}
103+
}
104+
105+
.combobox {
106+
height: initial;
107+
overflow: hidden;
108+
109+
.mainRow {
110+
cursor: pointer;
111+
position: relative;
112+
113+
.arrow {
114+
position: absolute;
115+
right: -6px;
116+
top: 4px;
117+
width: 16px;
118+
height: 16px;
119+
120+
transform: rotate(0deg);
121+
transition: transform 0.5s;
122+
123+
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAGdJREFUOI3tzjsOwjAURNGDUqSgTxU5K2AVrJtswjUsgHSR0qdxAZZFPrS+3ZvRzBsqf9MUtBtazJk+oMe0VTriiZCFX8nbpENMgfARjsn74vKj5IFruhfc8d6zIF9S/Hyk5HS4spMVeFcOjszaOwMAAAAASUVORK5CYII=');
124+
background-repeat: no-repeat;
125+
126+
}
127+
128+
&.expanded {
129+
.arrow {
130+
transform: rotate(-180deg);
131+
}
132+
}
133+
}
134+
135+
.dropList {
136+
transition: height 0.5s;
137+
margin-top: 0.5em;
138+
}
139+
}
140+
</style>

‎src/fields/fieldDate.vue

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<template lang="jade">
2+
input.form-control(type="date", v-model="value", :min="schema.min", :max="schema.max", :disabled="disabled", :placeholder="schema.placeholder")
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
import moment from "moment";
8+
9+
let inputFormat = "YYYY-MM-DD";
10+
11+
export default {
12+
mixins: [ abstractField ],
13+
14+
methods: {
15+
16+
formatValueToField(value) {
17+
if (value != null)
18+
return moment(value, this.schema.format).format(inputFormat);
19+
20+
return value;
21+
},
22+
23+
formatValueToModel(value) {
24+
if (value != null) {
25+
let m = moment(value, inputFormat);
26+
if (this.schema.format)
27+
value = m.format(this.schema.format);
28+
else
29+
value = m.toDate().valueOf();
30+
}
31+
32+
return value;
33+
}
34+
35+
}
36+
}
37+
</script>
38+
39+
40+
<style lang="sass" scoped>
41+
input {
42+
width: 100%;
43+
}
44+
</style>

‎src/fields/fieldEmail.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<template lang="jade">
2+
input.form-control(type="email", v-model="value", :disabled="disabled", :placeholder="schema.placeholder")
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
export default {
8+
mixins: [ abstractField ]
9+
}
10+
</script>
11+
12+
13+
<style lang="sass" scoped>
14+
input {
15+
width: 100%;
16+
}
17+
</style>

‎src/fields/fieldLabel.vue

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<template lang="jade">
2+
span {{ value }}
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
8+
export default {
9+
mixins: [ abstractField ]
10+
}
11+
</script>
12+
13+
<style lang="sass" scoped>
14+
span {
15+
display: block;
16+
width: 100%;
17+
}
18+
</style>

‎src/fields/fieldNumber.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<template lang="jade">
2+
input.form-control(type="number", v-model="value", number, :min="schema.min", :max="schema.max", :disabled="disabled", :placeholder="schema.placeholder")
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
export default {
8+
mixins: [ abstractField ]
9+
}
10+
</script>
11+
12+
13+
<style lang="sass" scoped>
14+
input {
15+
width: 100%;
16+
}
17+
</style>

‎src/fields/fieldPassword.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<template lang="jade">
2+
input.form-control(type="password", v-model="value", :readonly="schema.readonly", :disabled="disabled", :placeholder="schema.placeholder")
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
8+
export default {
9+
mixins: [ abstractField ]
10+
}
11+
</script>
12+
13+
<style lang="sass" scoped>
14+
input {
15+
width: 100%;
16+
}
17+
</style>

‎src/fields/fieldRange.vue

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<template lang="jade">
2+
input.form-control(type="range", v-model="value", :min="schema.min", :max="schema.max", :disabled="disabled", :placeholder="schema.placeholder")
3+
.helpText {{ value }}
4+
</template>
5+
6+
<script>
7+
import abstractField from './abstractField';
8+
export default {
9+
mixins: [ abstractField ]
10+
}
11+
</script>
12+
13+
14+
<style lang="sass" scoped>
15+
input {
16+
width: 100%;
17+
}
18+
19+
.helpText {
20+
margin: auto 0.5em;
21+
}
22+
</style>

‎src/fields/fieldSelect.vue

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<template lang="jade">
2+
select.form-control(v-model="value", :disabled="disabled")
3+
option(v-for="item in items", :value="getItemID(item)") {{ getItemName(item) }}
4+
</template>
5+
6+
<script>
7+
import {isObject} from "lodash";
8+
import abstractField from './abstractField';
9+
10+
export default {
11+
mixins: [ abstractField ],
12+
13+
computed: {
14+
items() {
15+
let values = this.schema.values;
16+
if (typeof(values) == "function") {
17+
return values.apply(this, [this.model, this.schema]);
18+
} else
19+
return values;
20+
}
21+
},
22+
23+
methods: {
24+
getItemID(item) {
25+
if (isObject(item) && item.id)
26+
return item.id;
27+
28+
return item;
29+
},
30+
31+
getItemName(item) {
32+
if (isObject(item) && item.name)
33+
return item.name;
34+
35+
return item;
36+
}
37+
}
38+
}
39+
</script>
40+
41+
42+
<style lang="sass" scoped>
43+
select {
44+
width: 100%;
45+
}
46+
</style>

‎src/fields/fieldSelectEx.vue

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<template lang="jade">
2+
select.selectpicker(v-model="value", :disabled="disabled", :multiple="schema.multiSelect", :title="schema.placeholder", data-width="100%")
3+
option(v-for="item in items", :value="getItemID(item)") {{ getItemName(item) }}
4+
</template>
5+
6+
<script>
7+
import {isObject} from "lodash";
8+
import abstractField from './abstractField';
9+
10+
export default {
11+
mixins: [ abstractField ],
12+
13+
computed: {
14+
items() {
15+
let values = this.schema.values;
16+
if (typeof(values) == "function") {
17+
return values.apply(this, [this.model, this.schema]);
18+
} else
19+
return values;
20+
}
21+
},
22+
23+
methods: {
24+
getItemID(item) {
25+
if (isObject(item) && item.id)
26+
return item.id;
27+
28+
return item;
29+
},
30+
31+
getItemName(item) {
32+
if (isObject(item) && item.name)
33+
return item.name;
34+
35+
return item;
36+
}
37+
},
38+
39+
watch: {
40+
model: function() {
41+
$(this.$el).selectpicker("refresh");
42+
}
43+
},
44+
45+
ready() {
46+
$(this.$el).selectpicker("destroy").selectpicker(this.schema.selectOptions);
47+
}
48+
}
49+
</script>
50+
51+
52+
<style lang="sass">
53+
.bootstrap-select {
54+
.dropdown-menu li.selected .text{
55+
font-weight: bold;
56+
}
57+
}
58+
</style>

‎src/fields/fieldSlider.vue

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<template lang="jade">
2+
input.form-control(type="text", number, v-model="value", :data-slider-value="value", :data-slider-min="schema.min", :data-slider-max="schema.max", :disabled="disabled", :placeholder="schema.placeholder")
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
export default {
8+
mixins: [ abstractField ],
9+
10+
11+
watch: {
12+
model: function() {
13+
$(this.$el).slider("setValue", this.value);
14+
}
15+
},
16+
17+
ready() {
18+
$(this.$el).slider(this.schema.sliderOptions);
19+
}
20+
}
21+
</script>
22+
23+
24+
<style lang="sass">
25+
.slider.slider-horizontal {
26+
width: 100% !important;
27+
}
28+
</style>

‎src/fields/fieldStaticMap.vue

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<template lang="jade">
2+
img(:src="mapLink")
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
8+
export default {
9+
mixins: [ abstractField ],
10+
11+
computed: {
12+
mapLink() {
13+
if (this.model.address && this.model.address.geo)
14+
return `http://maps.googleapis.com/maps/api/staticmap?center=${this.model.address.geo.lat},${this.model.address.geo.lng}&zoom=8&scale=false&size=800x300&maptype=roadmap&format=png&visual_refresh=true&markers=size:mid%7Ccolor:0xff0000%7Clabel:%7C${this.model.address.city}`;
15+
}
16+
}
17+
}
18+
</script>
19+
20+
<style lang="sass" scoped>
21+
img {
22+
display: block;
23+
width: auto;
24+
max-width: 100%;
25+
}
26+
</style>

‎src/fields/fieldText.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<template lang="jade">
2+
input.form-control(type="text", v-model="value", :readonly="schema.readonly", :disabled="disabled", :placeholder="schema.placeholder")
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
8+
export default {
9+
mixins: [ abstractField ]
10+
}
11+
</script>
12+
13+
<style lang="sass" scoped>
14+
input {
15+
width: 100%;
16+
}
17+
</style>

‎src/fields/fieldTextArea.vue

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<template lang="jade">
2+
textarea.form-control(v-model="value", :rows="schema.rows || 2", :placeholder="schema.placeholder", :disabled="disabled", :maxlength="schema.max")
3+
</template>
4+
5+
<script>
6+
import abstractField from './abstractField';
7+
8+
export default {
9+
mixins: [ abstractField ]
10+
}
11+
</script>
12+
13+
14+
<style lang="sass" scoped>
15+
textarea {
16+
width: 100%;
17+
}
18+
</style>

‎src/formGenerator.vue

Lines changed: 334 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,334 @@
1+
<template lang="jade">
2+
.panel.panel-default
3+
.panel-heading Properties
4+
.panel-body
5+
table
6+
thead
7+
tbody
8+
tr(v-for="field in fields", v-if="fieldVisible(field)", :class="getFieldRowClasses(field)")
9+
td
10+
span.help(v-if="field.help")
11+
i.fa.fa-question-circle
12+
.helpText {{{field.help}}}
13+
14+
|{{ field.label }}
15+
td
16+
.field-wrap
17+
component(:is="getFieldType(field)", :disabled="fieldDisabled(field)", :model.sync="model", :schema.sync="field")
18+
.buttons(v-if="field.buttons && field.buttons.length > 0")
19+
button.btn.btn-default(v-for="btn in field.buttons", @click="btn.onclick(model, field)", :class="btn.classes") {{ btn.label }}
20+
.hint(v-if="field.hint") {{ field.hint }}
21+
.errors(v-if="field.errors && field.errors.length > 0")
22+
span(v-for="error in field.errors") {{ error }}
23+
</template>
24+
25+
<script>
26+
import Vue from "vue";
27+
import {each, isFunction, isNil, isArray, isString} from 'lodash';
28+
29+
// Load all fields from '../fields' folder
30+
let Fields = require.context('./fields/', false, /^\.\/field([\w-_]+)\.vue$/);
31+
let fieldComponents = {};
32+
each(Fields.keys(), (key) => {
33+
let compName = Vue.util.classify(key.replace(/^\.\//, "").replace(/\.vue/, ""));
34+
fieldComponents[compName] = Fields(key);
35+
});
36+
37+
38+
export default {
39+
components: fieldComponents,
40+
41+
props: [
42+
"schema",
43+
"options",
44+
"model",
45+
"multiple",
46+
"isNewModel"
47+
],
48+
49+
data () {
50+
return {
51+
errors: []
52+
}
53+
},
54+
55+
computed: {
56+
fields() {
57+
let res = [];
58+
each(this.schema.fields, (field) => {
59+
if (!this.multiple || field.multi === true)
60+
res.push(field);
61+
});
62+
63+
return res;
64+
}
65+
},
66+
67+
watch: {
68+
// Futás közbeni rekord váltáskor
69+
model: function() {
70+
if (this.options.validateAfterLoad === true && !this.isNewModel)
71+
this.$parent.validateForm();
72+
else
73+
this.clearValidationErrors();
74+
}
75+
},
76+
77+
ready() {
78+
// Legelső betöltés
79+
if (this.options.validateAfterLoad === true && !this.isNewModel)
80+
this.$parent.validateForm();
81+
else
82+
this.clearValidationErrors();
83+
},
84+
85+
methods: {
86+
getFieldRowClasses(field) {
87+
let baseClasses = {
88+
error: field.errors && field.errors.length > 0,
89+
disabled: this.fieldDisabled(field),
90+
featured: field.featured,
91+
required: field.required
92+
}
93+
94+
if (isArray(field.styleClasses)) {
95+
each(field.styleClasses, (c) => baseClasses[c] = true);
96+
}
97+
else if (isString(field.styleClasses)) {
98+
baseClasses[field.styleClasses] = true;
99+
}
100+
101+
return baseClasses;
102+
},
103+
104+
getFieldType(fieldSchema) {
105+
return "field-" + fieldSchema.type;
106+
},
107+
108+
fieldDisabled(field) {
109+
if (isFunction(field.disabled))
110+
return field.disabled(this.model);
111+
112+
if (isNil(field.disabled))
113+
return false;
114+
115+
return field.disabled;
116+
},
117+
118+
fieldVisible(field) {
119+
if (isFunction(field.visible))
120+
return field.visible(this.model);
121+
122+
if (isNil(field.visible))
123+
return true;
124+
125+
return field.visible;
126+
},
127+
128+
validate() {
129+
this.clearValidationErrors();
130+
131+
each(this.$children, (child) => {
132+
if (isFunction(child.validate))
133+
{
134+
let err = child.validate();
135+
Array.prototype.push.apply(this.errors, err);
136+
}
137+
});
138+
139+
return this.errors.length == 0;
140+
},
141+
142+
clearValidationErrors() {
143+
this.errors.splice(0);
144+
145+
each(this.$children, (child) => {
146+
child.clearValidationErrors();
147+
});
148+
}
149+
}
150+
}
151+
</script>
152+
153+
<style lang="sass" scoped>
154+
155+
$errorColor: lighten(#F00, 0%);
156+
157+
table {
158+
width: 70%;
159+
min-width: 350px;
160+
margin: auto;
161+
162+
font-family: "Open Sans";
163+
font-size: 14px;
164+
165+
input, select, textarea {
166+
font-family: "Open Sans";
167+
font-size: 14px;
168+
169+
border-radius: 4px;
170+
border: 1px solid #BBB;
171+
padding: 2px 5px;
172+
}
173+
174+
td {
175+
padding: 0.3em 0.4em;
176+
177+
&:nth-child(1) {
178+
text-align: right;
179+
vertical-align: top;
180+
padding: 0.8em 0.5em;
181+
182+
span.help {
183+
margin-right: 0.3em;
184+
position: relative;
185+
186+
.helpText {
187+
background-color: #444;
188+
bottom: 30px;
189+
color: #fff;
190+
display: block;
191+
left: 0px;
192+
//margin-bottom: 15px;
193+
opacity: 0;
194+
padding: 20px;
195+
pointer-events: none;
196+
position: absolute;
197+
text-align: justify;
198+
width: 300px;
199+
//transform: translateY(10%);
200+
transition: all .25s ease-out;
201+
box-shadow: 2px 2px 6px rgba(0, 0, 0, 0.5);
202+
border-radius: 6px;
203+
204+
a {
205+
font-weight: bold;
206+
text-decoration: underline;
207+
}
208+
}
209+
210+
/* This bridges the gap so you can mouse into the tooltip without it disappearing */
211+
.helpText:before {
212+
bottom: -20px;
213+
content: " ";
214+
display: block;
215+
height: 20px;
216+
left: 0;
217+
position: absolute;
218+
width: 100%;
219+
}
220+
221+
/* CSS Triangles - see Trevor's post */
222+
/*.helpText:after {
223+
border-left: solid transparent 10px;
224+
border-right: solid transparent 10px;
225+
border-top: solid #1496bb 10px;
226+
bottom: -10px;
227+
content: " ";
228+
height: 0;
229+
left: 50%;
230+
margin-left: -13px;
231+
position: absolute;
232+
width: 0;
233+
}*/
234+
235+
&:hover .helpText {
236+
opacity: 1;
237+
pointer-events: auto;
238+
transform: translateY(0px);
239+
}
240+
}
241+
} // nth-child(1)
242+
243+
&:nth-child(2) {
244+
245+
> .field-wrap {
246+
display: flex;
247+
248+
.buttons {
249+
white-space: nowrap;
250+
button {
251+
display: inline-block;
252+
margin: 0 2px;
253+
}
254+
}
255+
}
256+
257+
.hint {
258+
font-style: italic;
259+
font-size: 0.8em;
260+
}
261+
262+
.errors {
263+
264+
}
265+
266+
} // nth-child(2)
267+
268+
} // td
269+
270+
tr.featured {
271+
td:nth-child(1) {
272+
font-weight: bold;
273+
}
274+
}
275+
276+
tr.required {
277+
td:nth-child(1):after {
278+
content: "*";
279+
font-weight: normal;
280+
color: Red;
281+
padding-left: 0.1em;
282+
font-size: 0.8em;
283+
position: absolute;
284+
margin-top: -0.4em;
285+
}
286+
}
287+
288+
289+
tr.disabled {
290+
td:nth-child(1) {
291+
color: #666;
292+
font-style: italic;
293+
}
294+
}
295+
296+
tr.company {
297+
/* csak teszt */
298+
background-color: #EEE;
299+
300+
}
301+
302+
tr.error {
303+
304+
td:nth-child(1) {
305+
//color: $errorColor;
306+
}
307+
308+
td:nth-child(2) {
309+
input:not([type="checkbox"]), textarea, select {
310+
border: 1px solid $errorColor;
311+
background-color: rgba($errorColor, 0.15);
312+
}
313+
}
314+
315+
.errors {
316+
color: $errorColor;
317+
font-size: 0.80em;
318+
span {
319+
display: block;
320+
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAiklEQVR4Xt2TMQoCQQxF3xdhu72MpZU3GU/meBFLOztPYrVWsQmEWSaMsIXgK8P8RyYkMjO2sAN+K9gTIAmDAlzoUzE7p4IFytvDCQWJKSStYB2efcAvqZFM0BcstMx5naSDYFzfLhh/4SmRM+6Agw/xIX0tKEDFufeDNRUc4XqLRz3qabVIf3BMHwl6Ktexn3nmAAAAAElFTkSuQmCC');
321+
background-repeat: no-repeat;
322+
padding-left: 17px;
323+
padding-top: 0px;
324+
margin-top: 0.2em;
325+
font-weight: 600;
326+
}
327+
328+
} // .errors
329+
330+
331+
} // tr.error
332+
333+
} // table
334+
</style>

‎src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
module.exports = require("./formGenerator.vue");
2+

0 commit comments

Comments
 (0)
Please sign in to comment.