Skip to content

Commit 0e979a3

Browse files
committed
Merge branch 'master-origin'
* master-origin: fix issue with null values on datetime 2.3.3 releases added newline migrated VFG docs to newer GitBooks, created GitHub Repo for Docs to allow for easier maintenance, updated JSFiddle to use "latest" VFG, and created a CodePen version as well code fix fixes an issue with fieldPikaday modifying the field schema and attaching `this.$el` to it, the pikadayOptions are now stored as `this.options` and created with `defaults({}, this.schema.pikadayOptions, {...})` to prevent this Codacy (guard-for-in) fix fixed code structure added "options" to VFG install function, appending custom "validators" to the validators object that are passed into `Vue.use(VueFormGenerator, { validators: { key: (value, field, model) => {} }) added an optional "unique" flag to "getFieldID" that appends lodash "uniqueId" to the ID when true. Fixes vue-generators#468 fixed single-quotes added "type" attribute to inside buttons schema, defaults to "button" when one is not provided fixes vue-generators#480 - dates are always passed to "date" and "datetime-local" elements using the standard format (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss), and "datetime" elements are converted into "datetime-local" (datetime is deprecated/obsolete). added "item.disabled" logic, supporting both boolean values and a function that is passed a reference to the model to determine disabled logic based on the model. listen for model-updated from `fields`, and fix `debounceFormatFunction` property to match fieldInput's `debounceFormatFunc` instead. Fix required number input does not require a value feat: add maxElements slot to fieldVueMultiSelect
2 parents d81bf48 + df67afc commit 0e979a3

19 files changed

+143
-47
lines changed

CHANGELOG.md

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
## <small>2.3.3 (2018-12-14)</small>
2+
3+
* #535, #526 - reversed "deep property path" fix ([da32bde](https://github.com/vue-generators/vue-form-generator/commit/da32bde)), closes [#535](https://github.com/vue-generators/vue-form-generator/issues/535) [#526](https://github.com/vue-generators/vue-form-generator/issues/526)
4+
* added "item.disabled" logic, supporting both boolean values and a function that is passed a referenc ([b227eb4](https://github.com/vue-generators/vue-form-generator/commit/b227eb4))
5+
* added "options" to VFG install function, appending custom "validators" to the validators object that ([892469e](https://github.com/vue-generators/vue-form-generator/commit/892469e))
6+
* added "type" attribute to inside buttons schema, defaults to "button" when one is not provided ([3306893](https://github.com/vue-generators/vue-form-generator/commit/3306893))
7+
* added an optional "unique" flag to "getFieldID" that appends lodash "uniqueId" to the ID when true. ([ab1daeb](https://github.com/vue-generators/vue-form-generator/commit/ab1daeb)), closes [#468](https://github.com/vue-generators/vue-form-generator/issues/468)
8+
* added newline ([5813f0a](https://github.com/vue-generators/vue-form-generator/commit/5813f0a))
9+
* Codacy (guard-for-in) fix ([4e81d2d](https://github.com/vue-generators/vue-form-generator/commit/4e81d2d))
10+
* code fix ([b3a1010](https://github.com/vue-generators/vue-form-generator/commit/b3a1010))
11+
* Fix required number input does not require a value ([f95b38c](https://github.com/vue-generators/vue-form-generator/commit/f95b38c))
12+
* fixed code structure ([3b750b3](https://github.com/vue-generators/vue-form-generator/commit/3b750b3))
13+
* fixed single-quotes ([dfee175](https://github.com/vue-generators/vue-form-generator/commit/dfee175))
14+
* fixes #480 - dates are always passed to "date" and "datetime-local" elements using the standard form ([db3413f](https://github.com/vue-generators/vue-form-generator/commit/db3413f)), closes [#480](https://github.com/vue-generators/vue-form-generator/issues/480)
15+
* fixes an issue with fieldPikaday modifying the field schema and attaching `this.$el` to it, the pika ([2024204](https://github.com/vue-generators/vue-form-generator/commit/2024204))
16+
* listen for model-updated from `fields`, and fix `debounceFormatFunction` property to match fieldInpu ([7ad1fca](https://github.com/vue-generators/vue-form-generator/commit/7ad1fca))
17+
* migrated VFG docs to newer GitBooks, created GitHub Repo for Docs to allow for easier maintenance, u ([d372f5b](https://github.com/vue-generators/vue-form-generator/commit/d372f5b))
18+
* feat: add maxElements slot to fieldVueMultiSelect ([2e91a2f](https://github.com/vue-generators/vue-form-generator/commit/2e91a2f))
19+
20+
21+
122
## <small>2.3.2 (2018-10-22)</small>
223

324
* Export dist ([9912b5e](https://github.com/vue-generators/vue-form-generator/commit/9912b5e))

README.md

+6-4
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ A schema-based form generator component for Vue.js.
1515

1616
## Demo
1717

18-
[JSFiddle simple example](https://jsfiddle.net/icebob/0mg1v81e/)
18+
[JSFiddle simple example](https://jsfiddle.net/zoul0813/d8excp36/)
1919

20-
[![Screenshot](https://icebob.gitbooks.io/vueformgenerator/content/assets/vfg-example1.png)](https://jsfiddle.net/icebob/0mg1v81e/)
20+
[CodePen simple example](https://codepen.io/zoul0813/pen/OrNVNw)
21+
22+
[![Screenshot](https://github.com/vue-generators/vue-form-generator-docs/raw/master/assets/vfg-example1.png)](https://jsfiddle.net/zoul0813/d8excp36/)
2123

2224
## Features
2325

@@ -33,7 +35,7 @@ A schema-based form generator component for Vue.js.
3335

3436
## Documentation
3537

36-
[Online documentation on Gitbook](https://icebob.gitbooks.io/vueformgenerator/content/)
38+
[Online documentation on Gitbook](https://vue-generators.gitbook.io/vue-generators/)
3739

3840
## Dependencies
3941

@@ -43,7 +45,7 @@ While built-in fields don't need external dependencies, optional fields may need
4345
These dependencies fall into two camps: jQuery or Vanilla. You can find almost the same functionality in both flavors.
4446
In the end, it's your choice to depend on jQuery or not.
4547

46-
You can find details about dependencies in the official [documentation](https://icebob.gitbooks.io/vueformgenerator/content/) under each specific component.
48+
You can find details about dependencies in the official [documentation](https://vue-generators.gitbook.io/vue-generators/) under each specific component.
4749

4850
## Installation
4951

bower.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-form-generator",
3-
"version": "2.3.2",
3+
"version": "2.3.3",
44
"homepage": "https://github.com/vue-generators/vue-form-generator/",
55
"authors": [
66
"Icebob"

dist/vfg-core.css

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/vfg-core.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/vfg.css

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/vfg.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-form-generator",
3-
"version": "2.3.2",
3+
"version": "2.3.3",
44
"description": "A schema-based form generator component for Vue.js",
55
"homepage": "https://github.com/vue-generators/vue-form-generator/",
66
"main": "dist/vfg.js",

src/fields/abstractField.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { get as objGet, forEach, isFunction, isString, isArray, debounce } from "lodash";
1+
import { get as objGet, forEach, isFunction, isString, isArray, debounce, uniqueId } from "lodash";
22
import validators from "../utils/validators";
33
import { slugifyFormID } from "../utils/schema";
44

@@ -31,7 +31,7 @@ export default {
3131
return {
3232
errors: [],
3333
debouncedValidateFunc: null,
34-
debouncedFormatFunction: null
34+
debouncedFormatFunc: null
3535
};
3636
},
3737

@@ -208,9 +208,9 @@ export default {
208208
}
209209
},
210210

211-
getFieldID(schema) {
211+
getFieldID(schema, unique = false) {
212212
const idPrefix = objGet(this.formOptions, "fieldIdPrefix", "");
213-
return slugifyFormID(schema, idPrefix);
213+
return slugifyFormID(schema, idPrefix) + (unique ? "-" + uniqueId() : "");
214214
},
215215

216216
getFieldClasses() {

src/fields/core/fieldChecklist.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
.listbox.form-control(v-if="schema.listBox", :disabled="disabled")
44
.list-row(v-for="item in items", :class="{'is-checked': isItemChecked(item)}")
55
label
6-
input(:id="getFieldID(schema)", type="checkbox", :checked="isItemChecked(item)", :disabled="disabled", @change="onChanged($event, item)", :name="getInputName(item)", v-attributes="'input'")
6+
input(:id="getFieldID(schema, true)", type="checkbox", :checked="isItemChecked(item)", :disabled="disabled", @change="onChanged($event, item)", :name="getInputName(item)", v-attributes="'input'")
77
| {{ getItemName(item) }}
88

99
.combobox.form-control(v-if="!schema.listBox", :disabled="disabled")
@@ -14,7 +14,7 @@
1414
.dropList
1515
.list-row(v-if="comboExpanded", v-for="item in items", :class="{'is-checked': isItemChecked(item)}")
1616
label
17-
input(:id="getFieldID(schema)", type="checkbox", :checked="isItemChecked(item)", :disabled="disabled", @change="onChanged($event, item)", :name="getInputName(item)", v-attributes="'input'")
17+
input(:id="getFieldID(schema, true)", type="checkbox", :checked="isItemChecked(item)", :disabled="disabled", @change="onChanged($event, item)", :name="getInputName(item)", v-attributes="'input'")
1818
| {{ getItemName(item) }}
1919
</template>
2020

src/fields/core/fieldInput.vue

+35-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
.wrapper(v-attributes="'wrapper'")
33
input.form-control(
44
:id="getFieldID(schema)",
5-
:type="schema.inputType.toLowerCase()",
5+
:type="inputType",
66
:value="value",
77
@input="onInput",
88
@blur="onBlur",
@@ -53,6 +53,16 @@ const DATETIME_FORMATS = {
5353
5454
export default {
5555
mixins: [abstractField],
56+
computed: {
57+
inputType() {
58+
if(this.schema && this.schema.inputType === "datetime") {
59+
// convert "datetime" to "datetime-local" (datetime deprecated in favor of "datetime-local")
60+
// ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime
61+
return "datetime-local";
62+
}
63+
return this.schema.inputType;
64+
}
65+
},
5666
methods: {
5767
formatValueToModel(value) {
5868
if (value != null) {
@@ -71,6 +81,15 @@ export default {
7181
7282
return value;
7383
},
84+
formatValueToField(value) {
85+
switch(this.schema.inputType.toLowerCase()) {
86+
case "date":
87+
case "datetime":
88+
case "datetime-local":
89+
return this.formatDatetimeValueToField(value);
90+
}
91+
return value;
92+
},
7493
formatDatetimeToModel(newValue, oldValue) {
7594
let defaultFormat = DATETIME_FORMATS[this.schema.inputType.toLowerCase()];
7695
let m = fecha.parse(newValue, defaultFormat);
@@ -83,6 +102,21 @@ export default {
83102
}
84103
this.updateModelValue(newValue, oldValue);
85104
},
105+
formatDatetimeValueToField(value) {
106+
if(value === null || undefined === value) {
107+
return null;
108+
}
109+
110+
let defaultFormat = DATETIME_FORMATS[this.schema.inputType.toLowerCase()];
111+
let m = value;
112+
if(!isNumber(value)) {
113+
m = fecha.parse(value, defaultFormat);
114+
}
115+
if(m !== false) {
116+
return fecha.format(m, defaultFormat);
117+
}
118+
return value;
119+
},
86120
formatNumberToModel(newValue, oldValue) {
87121
if (!isNumber(newValue)) {
88122
newValue = NaN;

src/fields/core/fieldRadios.vue

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<template lang="pug">
22
.radio-list(:disabled="disabled", v-attributes="'wrapper'")
33
label(v-for="item in items", :class="{'is-checked': isItemChecked(item)}", v-attributes="'label'")
4-
input(:id="getFieldID(schema)", type="radio", :disabled="disabled", :name="id", @click="onSelection(item)", :value="getItemValue(item)", :checked="isItemChecked(item)", :class="schema.fieldClasses", :required="schema.required", v-attributes="'input'")
4+
input(:id="getFieldID(schema, true)", type="radio", :disabled="isItemDisabled(item)", :name="id", @click="onSelection(item)", :value="getItemValue(item)", :checked="isItemChecked(item)", :class="schema.fieldClasses", :required="schema.required", v-attributes="'input'")
55
| {{ getItemName(item) }}
66

77
</template>
88

99
<script>
10-
import { isObject } from "lodash";
10+
import { isObject, isFunction, get as objGet } from "lodash";
1111
import abstractField from "../abstractField";
1212
1313
export default {
@@ -64,6 +64,16 @@ export default {
6464
isItemChecked(item) {
6565
let currentValue = this.getItemValue(item);
6666
return currentValue === this.value;
67+
},
68+
isItemDisabled(item) {
69+
if (this.disabled) {
70+
return true;
71+
}
72+
let disabled = objGet(item, "disabled", false);
73+
if (isFunction(disabled)) {
74+
return disabled(this.model);
75+
}
76+
return disabled;
6777
}
6878
}
6979
};

src/fields/optional/fieldPikaday.vue

+30-20
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,56 @@
44

55
<script>
66
import abstractField from "../abstractField";
7-
import { defaults } from "lodash";
7+
import { defaults, get as objGet } from "lodash";
88
import dateFieldHelper from "../../utils/dateFieldHelper";
99
1010
let inputFormat = "YYYY-MM-DD";
1111
1212
export default {
13-
mixins: [abstractField],
13+
mixins: [ abstractField ],
1414
data() {
15-
return { picker: null };
15+
return {
16+
picker: null,
17+
options: null
18+
};
1619
},
1720
1821
methods: {
1922
getDateFormat() {
20-
if (this.schema.pikadayOptions && this.schema.pikadayOptions.format) return this.schema.pikadayOptions.format;
21-
else return inputFormat;
23+
return objGet(this.schema, "pikadayOptions.format", inputFormat);
2224
},
25+
...dateFieldHelper,
26+
initialize(options) {
27+
if(this.picker && this.picker.destroy) {
28+
// if an existing picker is already set, destroy it first
29+
this.picker.destroy();
30+
}
2331
24-
...dateFieldHelper
25-
},
26-
27-
mounted() {
28-
this.$nextTick(() => {
29-
if (window.Pikaday) {
30-
this.picker = new window.Pikaday(
31-
defaults(this.schema.pikadayOptions || {}, {
32+
this.$nextTick(() => {
33+
if (window.Pikaday) {
34+
this.options = defaults({}, options, {
3235
field: this.$el, // bind the datepicker to a form field
3336
onSelect: () => {
3437
this.value = this.picker.toString();
3538
}
3639
// trigger: , // use a different element to trigger opening the datepicker, see [trigger example][] (default to `field`)
37-
})
38-
);
39-
} else {
40-
console.warn("Pikaday is missing. Please download from https://github.com/dbushell/Pikaday/ and load the script and CSS in the HTML head section!");
41-
}
42-
});
40+
});
41+
this.picker = new window.Pikaday(this.options);
42+
} else {
43+
console.warn("Pikaday is missing. Please download from https://github.com/dbushell/Pikaday/ and load the script and CSS in the HTML head section!");
44+
}
45+
});
46+
}
47+
},
48+
49+
mounted() {
50+
this.initialize(objGet(this.schema, "pikadayOptions", {}));
4351
},
4452
4553
beforeDestroy() {
46-
if (this.picker) this.picker.destroy();
54+
if (this.picker) {
55+
this.picker.destroy();
56+
}
4757
}
4858
};
4959
</script>

src/fields/optional/fieldVueMultiSelect.vue

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
)
4444
span(slot="noResult").
4545
{{ selectOptions.noResult }}
46+
span(slot="maxElements").
47+
{{ selectOptions.maxElements }}
4648
</template>
4749
<script>
4850
import abstractField from "../abstractField";

src/formGenerator.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
div.vue-form-generator(v-if='schema != null')
33
fieldset(v-if="schema.fields", :is='tag')
44
template(v-for='field in fields')
5-
form-group(v-if='fieldVisible(field)', :vfg="vfg", :field="field", :errors="errors", :model="model", :options="options", @validated="onFieldValidated")
5+
form-group(v-if='fieldVisible(field)', :vfg="vfg", :field="field", :errors="errors", :model="model", :options="options", @validated="onFieldValidated", @model-updated="onModelUpdated")
66

77
template(v-for='group in groups')
88
fieldset(:is='tag', :class='getFieldRowClasses(group)')

src/formGroup.vue

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<div class="field-wrap">
1212
<component ref="child" :is="getFieldType(field)" :vfg="vfg" :disabled="fieldDisabled(field)" :model="model" :schema="field" :formOptions="options" @model-updated="onModelUpdated" @validated="onFieldValidated"></component>
1313
<div v-if="buttonVisibility(field)" class="buttons">
14-
<button v-for="(btn, index) in field.buttons" @click="buttonClickHandler(btn, field, $event)" :class="btn.classes" :key="index" v-text="btn.label"></button>
14+
<button v-for="(btn, index) in field.buttons" @click="buttonClickHandler(btn, field, $event)" :class="btn.classes" :key="index" v-text="btn.label" :type="getButtonType(btn)"></button>
1515
</div>
1616
</div>
1717

@@ -81,6 +81,10 @@ export default {
8181
getFieldType(fieldSchema) {
8282
return "field-" + fieldSchema.type;
8383
},
84+
// Get type of button, default to 'button'
85+
getButtonType(btn) {
86+
return objGet(btn, "type", "button");
87+
},
8488
// Child field executed validation
8589
onFieldValidated(res, errors, field) {
8690
this.$emit("validated", res, errors, field);

src/index.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,15 @@ const schema = require("./utils/schema.js");
33
const validators = require("./utils/validators.js").default;
44
const fieldComponents = require("./utils/fieldsLoader").default;
55
const abstractField = require("./fields/abstractField").default;
6-
const install = (Vue) => {
6+
const install = (Vue, options) => {
77
Vue.component("VueFormGenerator", module.exports.component);
8+
if (options && options.validators) {
9+
for (let key in options.validators) {
10+
if ({}.hasOwnProperty.call(options.validators, key)) {
11+
validators[key] = options.validators[key];
12+
}
13+
}
14+
}
815
};
916

1017
module.exports = {

src/utils/validators.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { defaults, isNil, isNumber, isInteger, isString, isArray, isFunction } from "lodash";
1+
import { defaults, isNil, isNumber, isInteger, isString, isArray, isFunction, isFinite } from "lodash";
22
import fecha from "fecha";
33

44
let resources = {
@@ -66,7 +66,7 @@ const validators = {
6666
if (res != null) return res;
6767

6868
let err = [];
69-
if (isNumber(value)) {
69+
if (isFinite(value)) {
7070
if (!isNil(field.min) && value < field.min) {
7171
err.push(msg(messages.numberTooSmall, field.min));
7272
}

test/unit/specs/utils/validators.spec.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ describe("Validators", () => {
3131
check(v.number, null, field, 1);
3232
});
3333

34+
it("should give error if value is NaN or Infinity", () => {
35+
check(v.number, NaN, field, 1);
36+
check(v.number, Infinity, field, 1);
37+
check(v.number, -Infinity, field, 1);
38+
});
39+
3440
it("should give error if value is smaller than min", () => {
3541
check(v.number, -1, field, 1);
3642
check(v.number, 0, field, 1);
@@ -68,7 +74,7 @@ describe("Validators", () => {
6874
// invalid integer
6975
check(v.integer, 3.14, field, 1);
7076
// invalid number, invalid integer
71-
check(v.integer, "3.14", field, 2);
77+
check(v.integer, NaN, field, 2);
7278
});
7379

7480
it("should not give error if value is integer", () => {

0 commit comments

Comments
 (0)