From 690bb8571999e0bb71aef48f95761ed32f5534c6 Mon Sep 17 00:00:00 2001 From: Jacques Mannon Date: Sun, 4 Jun 2017 14:39:21 +0200 Subject: [PATCH 1/3] added field validation functionality --- package.json | 1 + src/App.vue | 12 + src/components/VueEditortable.vue | 823 +++++++++++++++--------------- src/mixins/Validator.js | 59 +++ 4 files changed, 495 insertions(+), 400 deletions(-) create mode 100644 src/mixins/Validator.js diff --git a/package.json b/package.json index 0226018..78d1e97 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "dependencies": { "axios": "^0.16.1", + "validator": "^7.0.0", "vue": "^2.2.2", "vue-awesome": "^2.1.0", "vue-resource": "^1.2.1" diff --git a/src/App.vue b/src/App.vue index a361bbd..062ff89 100644 --- a/src/App.vue +++ b/src/App.vue @@ -28,6 +28,18 @@ title: 'Vorname', name: 'firstname', editable: true, + validator: { + rules: [ + 'required', + 'email', + 'contains:hansi', + ], + messages: [ + 'Field is required', + 'Wrong email format', + 'Must contain Hansi', + ], + }, }, { title: 'Nachname', diff --git a/src/components/VueEditortable.vue b/src/components/VueEditortable.vue index 16237c0..6848c08 100644 --- a/src/components/VueEditortable.vue +++ b/src/components/VueEditortable.vue @@ -1,125 +1,126 @@ @@ -137,6 +138,7 @@ import Icon from 'vue-awesome/components/Icon'; import Requests from '../mixins/Requests'; import Pagination from '../mixins/Pagination'; + import Validator from '../mixins/Validator'; export default { props: { @@ -158,7 +160,7 @@ components: { Icon, }, - mixins: [Requests, Pagination], + mixins: [Requests, Pagination, Validator], data() { const sortOrders = {}; this.data.columns.forEach((key) => { @@ -171,9 +173,9 @@ show: true, itemsPerPage: 25, itemsPerPageValues: [ - { text: 25, value: 25 }, - { text: 50, value: 50 }, - { text: 100, value: 100 }, + { text: 25, value: 25 }, + { text: 50, value: 50 }, + { text: 100, value: 100 }, ], }, requests: { @@ -514,7 +516,7 @@ } for (let i = startCol; i < l; i += 1) { if ((sumCols() + vm.columnsWidth[nextCol] <= vm.wrapperWidth) && vm.cols[l - 1].hidden - && vm.cols[nextCol].hidden && vm.cols[nextCol].show) { + && vm.cols[nextCol].hidden && vm.cols[nextCol].show) { vm.$set(vm.cols[nextCol], 'hidden', false); for (let ii = 0; ii < ll; ii += 1) { vm.$set(vm.tableData[ii][vm.cols[nextCol].name], 'isHidden', false); @@ -585,6 +587,11 @@ } else { obj.show = true; } + if (Object.prototype.hasOwnProperty.call(cols[i], 'validator')) { + obj.validator = cols[i].validator; + } else { + obj.validator = false; + } vm.cols.push(obj); obj = {}; } @@ -607,6 +614,7 @@ cell.isEditable = vm.cols[ii].editable; cell.isHidden = vm.cols[ii].hidden; cell.show = vm.cols[ii].show; + cell.hasErrors = []; row[vm.cols[ii].name] = cell; cell = {}; } @@ -627,11 +635,18 @@ } }, // save changed cell / post request - saveData(key, value, id) { + saveData(rowIndex, key, value, id) { const vm = this; - const postData = {}; - postData[key] = value; - const data = postData; + vm.showSavingIcon(key, rowIndex); + let errors = []; + vm.cols.forEach((obj) => { + if (obj.name === key) { + if (obj.validator) { + errors = vm.validate(obj.validator.rules, obj.validator.messages, value); + } + } + }); + vm.$set(vm.filteredData[rowIndex][key], 'hasErrors', errors); function cb() { vm.savingKey = false; vm.savingIndex = false; @@ -640,17 +655,25 @@ vm.savingKey = false; vm.savingIndex = false; } - if (vm.opt.requests.postUrl) { - const url = `${vm.opt.requests.patchUrl}/${id}`; - vm.patchData(url, data, cb, errorCb); - } - for (let i = 0; i < vm.cols.length; i += 1) { - if (vm.cols[i].name === key) { - vm.activeCol = i; - break; + if (errors.length === 0) { + console.log('inside save', errors.length); + const postData = {}; + postData[key] = value; + const data = postData; + if (vm.opt.requests.postUrl) { + const url = `${vm.opt.requests.patchUrl}/${id}`; + vm.patchData(url, data, cb, errorCb); } + for (let i = 0; i < vm.cols.length; i += 1) { + if (vm.cols[i].name === key) { + vm.activeCol = i; + break; + } + } + vm.initTableWidths(); + } else { + errorCb(); } - vm.initTableWidths(); }, // set sorting array and key, data gets filtered (computed) sortBy(key, event) { @@ -822,8 +845,8 @@ && !vm.filteredData[ri][cols[i + 1].name].isHidden) { vm.setTarget(ri, cols[i + 1].name); } else if (vm.filteredData[ri][cols[i + 1].name].isEditable - && vm.filteredData[ri][cols[i + 1].name].show - && vm.filteredData[ri][cols[i + 1].name].isHidden) { + && vm.filteredData[ri][cols[i + 1].name].show + && vm.filteredData[ri][cols[i + 1].name].isHidden) { vm.swipeRight(); vm.setTarget(ri, cols[i + 1].name); } else { @@ -832,8 +855,8 @@ } } else if (ri + 1 <= lastIndex) { if (vm.filteredData[ri + 1][cols[0].name].isEditable - && vm.filteredData[ri + 1][cols[0].name].show - && !vm.filteredData[ri + 1][cols[0].name].isHidden) { + && vm.filteredData[ri + 1][cols[0].name].show + && !vm.filteredData[ri + 1][cols[0].name].isHidden) { vm.tableWidth = vm.initTableWidth; vm.setTableWidth(); vm.setSelection(vm.filteredData[ri + 1][cols[0].name].value, event.key); @@ -851,8 +874,8 @@ vm.setTableWidth(); vm.setPage(vm.currentPage + 2); if (vm.filteredData[0][cols[0].name].isEditable - && vm.filteredData[0][cols[0].name].show - && !vm.filteredData[0][cols[0].name].isHidden) { + && vm.filteredData[0][cols[0].name].show + && !vm.filteredData[0][cols[0].name].isHidden) { vm.setSelection(vm.filteredData[0][cols[0].name].value, event.key); vm.setTarget(0, cols[0].name); } else { @@ -868,12 +891,12 @@ let ri = thisRowIndex; if (i - 1 >= 0) { if (vm.filteredData[ri][cols[i - 1].name].isEditable - && vm.filteredData[ri][cols[i - 1].name].show - && !vm.filteredData[ri][cols[i - 1].name].isHidden) { + && vm.filteredData[ri][cols[i - 1].name].show + && !vm.filteredData[ri][cols[i - 1].name].isHidden) { vm.setTarget(ri, cols[i - 1].name); } else if (vm.filteredData[ri][cols[i - 1].name].isEditable - && vm.filteredData[ri][cols[i - 1].name].show - && vm.filteredData[ri][cols[i - 1].name].isHidden) { + && vm.filteredData[ri][cols[i - 1].name].show + && vm.filteredData[ri][cols[i - 1].name].isHidden) { vm.swipeLeft(); vm.setTarget(ri, cols[i - 1].name); } else { @@ -884,8 +907,8 @@ vm.tableWidth = vm.initTableWidth; vm.setTableWidthReverse(); if (vm.filteredData[ri - 1][cols[lastCol].name].isEditable - && vm.filteredData[ri - 1][cols[lastCol].name].show - && !vm.filteredData[ri - 1][cols[lastCol].name].isHidden) { + && vm.filteredData[ri - 1][cols[lastCol].name].show + && !vm.filteredData[ri - 1][cols[lastCol].name].isHidden) { vm.setSelection(vm.filteredData[ri - 1][cols[0].name].value, event.key); vm.setTarget(ri - 1, cols[lastCol].name); } else { @@ -901,8 +924,8 @@ vm.setTableWidthReverse(); vm.setPage(vm.currentPage); if (vm.filteredData[lastIndex][cols[lastCol].name].isEditable - && vm.filteredData[lastIndex][cols[lastCol].name].show - && !vm.filteredData[lastIndex][cols[lastCol].name].isHidden) { + && vm.filteredData[lastIndex][cols[lastCol].name].show + && !vm.filteredData[lastIndex][cols[lastCol].name].isHidden) { vm.setSelection(vm.filteredData[lastIndex][cols[0].name].value, event.key); vm.setTarget(lastIndex, cols[lastCol].name); } else { @@ -1041,277 +1064,277 @@ diff --git a/src/mixins/Validator.js b/src/mixins/Validator.js new file mode 100644 index 0000000..993637b --- /dev/null +++ b/src/mixins/Validator.js @@ -0,0 +1,59 @@ +import validator from 'validator'; + +export default { + methods: { + validate(rules, messages, value) { + const res = []; + rules.forEach((rule, key) => { + if (!this.makeValidation(rule, value)) { + res.push(messages[key]); + } + }); + return res; + }, + makeValidation(str, value) { + let res = false; + const arr = this.checkIfParameter(str); + const l = arr.length; + const string = arr[0]; + let paraOne; + let paraTwo; + if (l > 0) paraOne = arr[1]; + if (l > 1) paraTwo = arr[2]; + switch (string) { + case 'required': + res = !validator.isEmpty(value); + break; + case 'email': + res = validator.isEmail(value); + break; + case 'contains': + res = validator.contains(value, paraOne); + break; + case 'min': + res = validator.isInt(value, { min: paraOne }); + break; + case 'max': + res = validator.isInt(value, { max: paraOne }); + break; + case 'between': + res = validator.isInt(value, { min: paraOne, max: paraTwo }); + break; + default: + res = false; + } + return res; + }, + checkIfParameter(str) { + let i = 0; + let res; + i = str.indexOf(':'); + if (i > -1) { + res = str.split(':'); + } else { + res = [str]; + } + return res; + }, + }, +}; From 35c8d48be38c40d16f652ee544e590800fc9a2e1 Mon Sep 17 00:00:00 2001 From: Jacques Mannon Date: Sun, 4 Jun 2017 16:40:05 +0200 Subject: [PATCH 2/3] added validation rules & styling --- src/App.vue | 8 +--- src/components/VueEditortable.vue | 6 ++- src/mixins/Validator.js | 64 +++++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/App.vue b/src/App.vue index 062ff89..eec5ea1 100644 --- a/src/App.vue +++ b/src/App.vue @@ -30,14 +30,10 @@ editable: true, validator: { rules: [ - 'required', - 'email', - 'contains:hansi', + 'ip4', ], messages: [ - 'Field is required', - 'Wrong email format', - 'Must contain Hansi', + 'Must be alpha', ], }, }, diff --git a/src/components/VueEditortable.vue b/src/components/VueEditortable.vue index 6848c08..853c548 100644 --- a/src/components/VueEditortable.vue +++ b/src/components/VueEditortable.vue @@ -91,7 +91,7 @@ -
{{ cell.hasErrors[0] }}
+
{{ cell.hasErrors[0] }}
@@ -1282,6 +1282,10 @@ #pagination a.btn.disabled:hover { background-color: #fff; } + .validation-error { + color: red; + font-size: 0.8em; + } @media only screen and (max-width: 713px) { table.vue-editortable { diff --git a/src/mixins/Validator.js b/src/mixins/Validator.js index 993637b..d68de66 100644 --- a/src/mixins/Validator.js +++ b/src/mixins/Validator.js @@ -30,14 +30,72 @@ export default { case 'contains': res = validator.contains(value, paraOne); break; + case 'int': + res = validator.isInt(value); + break; + case 'float': + res = validator.isFloat(value); + break; case 'min': - res = validator.isInt(value, { min: paraOne }); + if (validator.isInt(value)) { + res = validator.isInt(value, { min: parseInt(paraOne, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { min: parseFloat(paraOne, 10) }); + } break; case 'max': - res = validator.isInt(value, { max: paraOne }); + if (validator.isInt(value)) { + res = validator.isInt(value, { max: parseInt(paraOne, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { max: parseFloat(paraOne, 10) }); + } break; case 'between': - res = validator.isInt(value, { min: paraOne, max: paraTwo }); + if (validator.isInt(value)) { + res = validator.isInt(value, { min: parseInt(paraOne, 10), + max: parseInt(paraTwo, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { min: parseFloat(paraOne, 10), + max: parseFloat(paraTwo, 10) }); + } + break; + case 'gt': + if (validator.isInt(value)) { + res = validator.isInt(value, { gt: parseInt(paraOne, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { gt: parseFloat(paraOne, 10) }); + } + break; + case 'lt': + if (validator.isInt(value)) { + res = validator.isInt(value, { lt: parseInt(paraOne, 10) }); + } else if (validator.isFloat(value)) { + res = validator.isFloat(value, { lt: parseFloat(paraOne, 10) }); + } + break; + case 'alpha': + res = validator.isAlpha(value, paraOne); + break; + case 'alphaNum': + res = validator.isAlphanumeric(value, paraOne); + break; + case 'bool': + res = validator.isBoolean(value); + break; + case 'url': + res = validator.isURL(value); + break; + case 'fqdn': + res = validator.isFQDN(value); + break; + case 'hexColor': + res = validator.isHexColor(value); + break; + case 'ip4': + res = validator.isIP(value, 4); + break; + case 'ip6': + res = validator.isIP(value, 6); break; default: res = false; From 7900b97174f7c4dc76fac01b20d83fcc9799809e Mon Sep 17 00:00:00 2001 From: Jacques Mannon Date: Sun, 4 Jun 2017 16:40:54 +0200 Subject: [PATCH 3/3] updated gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 921ebb0..03d3c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules/ dist/ npm-debug.log -json/ \ No newline at end of file +json/ +notes.txt