Validation in JSONForm
Recently, I had created a user form with JSONForm. However, the form was embedded in another site with its own save
button. JSONForm usually adds its own submit
button to the site, but you easily can remove it. One of the problems left was how to trigger validation for the form manually once the site’s save
button was clicked. Be aware that this implies triggering validation from outside the HTML form
element. Whereas JSONForm’s submit
button resides inside the form
element as an <input type="button">
, my site’s save
button does not. Unfortunately, the description in the JSONForm’s Wiki pages was not really understandable to me. It took me a long time but I finally succeeded to trigger JSONForm validation manually. Here’s what I did.
JSONForm’s validation relies on its own adapted version of JSV.js. You have to make sure that this library is accessible to your JSONForm code. In the simplest case you can include the Javascript in your HTML site before the jsonform library. (I renamed the file to jsonform-jsv.js
to make clear that this is a modified version of JSV.js.)
In my case though all Javascript files were pre-compiled into a single, big, compressed file with Browserify and only this file was referenced from my HTML file. All Javascript libraries followed the Requirejs standard. Hence, the - theoretically - correct way to add another library such as JSV.js would be to use a require('JSV');
statement. In practice however this would not work, because doing so would actually imply loading the official version of JSV.js instead of JSONForm’s own adapted version. I finally settled with the solution to add the JSONForm’s version inside HTML together with the pre-compiled Javascript file:
Maybe not the most elegant solution, but it worked. It is important to understand that if you do not provide a JSV library, then clicking JSONForm’s submit
button will actually trigger the HTML5 compliant browser-internal form validation. This is not really what you want to happen, as there are some important differences between JSONForm’s own validation procedure and the one provided internally by most modern browsers. For instance, JSONForm renders input elements with type="number"
actually as text inputs but validates them as number inputs, whereas the HTML5 compliant browser-internal validation validates them as text input.
So, I still had to trigger the validation manually. This involved several steps. The problem is that there exists code for validation inside the JSONForm Javascript library, but unfortunately it is tightly bound to the submit
button click. I did not want to change any code inside the JSONForm library and try to expose the validation function to the outside world. There are however two other exposed functions that I could rely upon: myFormEl.jsonFormValue()
and myFormEl.jsonFormErrors(errors, options)
. The first method returns all entered form values, the second one highlights invalid form input elements.
Thus, in my site’s save
function, added the following code:
There’s quite a lot contained in this code snippet, so let’s break it down.
-
var formEl = $('#myForm');
This line uses JQuery to get the HTML form element with the id of#myForm
. You could achieve this without JQuery (e.g.document.getElementById('myForm')
, but since JSONForm requires JQuery anyway, why not use it? -
var env = JSONFormValidator.createEnvironment("json-schema-draft-03");
Here we create a new JSV validator environment. This assumes that the variableJSONFormValidator
is globally accessible. Alternatively,JSV.createEnvironment("json-schema-draft-03")
would achieve the same. -
var schema = { 'properties': myJsonForm.schema };
This one took me long to figure out.myJsonForm.schema
refers to the JSONForm’sschema
property you had to define for creating the HTML form. Be aware how I wrapped the schema inside another object as a value of a property calledproperties
. This is important! If you simply usemyJsonForm.schema
directly, the validation will never indicate any errors. -
var report = env.validate(formEl.jsonFormValue(), schema);
This code actually triggers the validation. We retrieve the user input withformEl.jsonFormValue()
and use it together with the schema as an input to the validation function. Report will be an object containing anerrors
property, this is what we will need for further processing. If there are no errors, thenreport.errors.length
will be 0. If it has length > 0 then there are errors. I used this information to abort the saving procedure. -
var options = {}; formEl.jsonFormErrors(report.errors, options);
options
is simply an empty object. In the current JSONForm version, it does not serve any purpose, but it is still needed as a function parameter. CallingformEl.jsonFormErrors(...)
will highlight invalid input elements on the page and also show a short error message to the user.
Some remarks. First, JSONForm’s logic how to render certain specified input types to input elements is not always intuitive. For example, the schema specification "foo": { "type": "number" }
results in an input element of type text: <input type="text">
. JSONForm on the default mapping:
- A
number
property generates a text input, i.e. an <input type="text"> element.- An
integer
property generates a text input as well, i.e. an <input type="text"> element.
What is even stranger is that specifying type="number"
in the form section atually renders <input type="number">
elements.
Second, having an input fields set to readonly
resulted in validation errors if I had specified this inside the schema section. It worked though if specified inside the form section.
Did not work | Worked |
---|---|
Third, when I was using JSONForm’s arrays of objects, setting an object property to required
in the schema section resulted in validation errors. If however specified in the form section, this did not seem to have any effect whatsoever, that is apparently no check was performed whether the required input fields were filled out or not.