diff --git a/docs/api.md b/docs/api.md
index 1110360..469216e 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -165,10 +165,11 @@ Constructs a new JSONEditor.
- `{function} onValidationError(errors)`
- Set a callback function for validation errors. Available in all modes.
+ Set a callback function for validation and parse errors. Available in all modes.
- On validation of the json, if errors were found this callback is invoked with the validation errors data.
- Between validations, the callback will be invoked only if the validation errors were changed.
+ On validation of the json, if errors of any kind were found this callback is invoked with the errors data.
+
+ On change, the callback will be invoked only if errors were changed.
Example:
@@ -178,6 +179,20 @@ Constructs a new JSONEditor.
* @param {Array} errors validation errors
*/
onValidationError: function (errors) {
+ errors.forEach((error) => {
+ switch (error.type) {
+ case 'validation': // schema validation error
+ ...
+ break;
+ case 'customValidation': // custom validation error
+ ...
+ break;
+ case 'error': // json parse error
+ ...
+ break;
+ ...
+ }
+ });
...
}
}
diff --git a/examples/22_on_validation_event.html b/examples/22_on_validation_event.html
index f8eac4e..2b289ca 100644
--- a/examples/22_on_validation_event.html
+++ b/examples/22_on_validation_event.html
@@ -131,7 +131,7 @@
onValidationError: function(errors) {
console.error('onValidationError', errors);
const outputEL = document.getElementById('onValidationOutput')
- outputEL.innerHTML = 'onValidationError
was called with ' + errors.length + ' errors
' +
+ outputEL.innerHTML = 'onValidationError
was called with ' + errors.length + ' error' + (errors.length > 1 ? 's' : '') + '
' +
'open the browser console to see the error objects';
},
onValidate: function (json) {
diff --git a/src/js/textmode.js b/src/js/textmode.js
index 98f7c67..b507c4b 100644
--- a/src/js/textmode.js
+++ b/src/js/textmode.js
@@ -804,7 +804,6 @@ textmode.validate = function () {
console.error('Custom validation function did throw an error', err)
})
} catch (err) {
- this.lastSchemaErrors = undefined
if (this.getText()) {
// try to extract the line number from the jsonlint error message
const match = /\w*line\s*(\d+)\w*/g.exec(err.message)
@@ -820,6 +819,13 @@ textmode.validate = function () {
}
this._renderErrors(parseErrors)
+
+ if (typeof this.options.onValidationError === 'function') {
+ if (isValidationErrorChanged(parseErrors, this.lastSchemaErrors)) {
+ this.options.onValidationError.call(this, parseErrors)
+ }
+ this.lastSchemaErrors = parseErrors
+ }
}
}
diff --git a/src/js/treemode.js b/src/js/treemode.js
index 25bcf46..7f541d1 100644
--- a/src/js/treemode.js
+++ b/src/js/treemode.js
@@ -563,7 +563,8 @@ treemode.validate = function () {
.map(function findNode (error) {
return {
node: root.findNode(error.dataPath),
- error: error
+ error: error,
+ type: 'validation'
}
})
.filter(function hasNode (entry) {
@@ -675,7 +676,8 @@ treemode._validateCustom = function (json) {
return {
node: node,
- error: error
+ error: error,
+ type: 'customValidation'
}
})
.filter(entry => entry && entry.node && entry.error && entry.error.message)
diff --git a/src/js/util.js b/src/js/util.js
index 0058474..a4bf66d 100644
--- a/src/js/util.js
+++ b/src/js/util.js
@@ -1464,7 +1464,12 @@ export function isValidationErrorChanged (currErr, prevErr) {
if (prevErr.length !== currErr.length) { return true }
for (let i = 0; i < currErr.length; ++i) {
- const pErr = prevErr.find(p => p.dataPath === currErr[i].dataPath && p.schemaPath === currErr[i].schemaPath)
+ let pErr
+ if (currErr[i].type === 'error') {
+ pErr = prevErr.find(p => p.line === currErr[i].line)
+ } else {
+ pErr = prevErr.find(p => p.dataPath === currErr[i].dataPath && p.schemaPath === currErr[i].schemaPath)
+ }
if (!pErr) {
return true
}
diff --git a/src/js/validationUtils.js b/src/js/validationUtils.js
index 2418b4c..0ec44ca 100644
--- a/src/js/validationUtils.js
+++ b/src/js/validationUtils.js
@@ -34,7 +34,8 @@ export function validateCustom (json, onValidate) {
.map(error => // change data structure into the structure matching the JSON schema errors
({
dataPath: stringifyPath(error.path),
- message: error.message
+ message: error.message,
+ type: 'customValidation'
}))
} else {
return []