Obviel Forms

Introduction

Obviel forms are a way to create web forms. Obviel forms are interactive and allow you to create complex forms with ease.

HTML forms

It is instructive to briefly examine HTML forms and patterns involving them, before we dive into the details of Obviel forms and how these patterns are implemented.

A HTML form consists of a HTML form element. Inside the form element are various input, textarea and select elements describing the fields of the form that the user can fill in. In addition there are one or more button or submit input elements that let the user submit the form, or cancel the submission. More complex JavaScript asssisted input widgets may also exist, for instance to allow the user to enter a date.

When the form is submitted, it is sent to a particular URL, identified with the action attribute on the form tag. This initiates a form submission. The entered data are encoded, either in the URL if the form is submitted with a GET request, or in a form data format when doing a POST submission.

The web server software or web framework on the server side that you use knows how to decode the form data, and then hands it to your application in some way, to take an action: for instance to add a record to a database.

When browser submits a form to the action URL, the action URL also sends back a HTML response, which the browser then displays. This can contain the results of the form processing.

Form patterns

Form handling in an application tends to follow certain patterns. We’ll discuss some of these patterns and their traditional implementation here.

Add forms and edit forms

An add form is used to add new information to the application: a blog entry, someone’s address, or whatever else is relevant to the application domain. Add forms are empty when they are displayed first: its fields are either empty or have a default value in them that the user can alter.

An edit form is used to change existing information in the application: change a blog entry, modify your user account data, and so on. Edit forms are shown filled-in when you open them: the fields show the information that you are about to change, and allows you to modify them.

Conversion and validation

When a form is submitted, a form needs to be validated: for instance checking whether a number is in range, or a text input is not too long, or a list is one of several allowed values. A very common validation is to make sure a required value was filled in at all.

When a form is submitted, form data also needs to be converted: for instance, numbers are inputed as text strings, and need to be converted to actual numbers that the underlying application can deal with. A checkbox may be turned into a true/false value, and a date string needs to be parsed into a date object. Conversion needs to take place before validation can take place.

Conversion and validation can be client-side or server-side.

Client-side validation, typically in JavaScript, lets the form give instant feedback to the user that is fillin in the form, before the user even submits the form. This increases the usability of the form, as the user does not need to wait for a relatively long submit/reload cycle in order to get this information. Client-side validation does not ensure that the user really inputs the allowed information however.

Server-side validation has the benefit of being secure: the server can validate that the data entered by the client is really allowed by the application. This is important especially if the web application faces the public.

A traditional pattern of doing HTML forms is doing no client-side validation at all except for what is offered by bare HTML, and doing all the validation on the server. To display validation errors a round-trip procedure is required, where the whole form is submitted to the server. If conversion or validation failed, the whole form is shown again showing validation errors, along with any values the user previously filled in.

Nesting and repeating fields

Advanced form patterns involve composite and repeating fields. A composite field is a field composed out of other fields. An example of a composite field is a date field that consists of three fields allowing you to enter the year, month and day separately from each other. A repeating field is a field where a list of values (sub-forms) needs to be entered. A form where you enter the crew of a ship for instance should allow you to enter more than one crew member, adding as many as you need.

In a form system without client-side code, a repeating field requires a complicated round-trip with the server. The server needs to have a sophisticated system for decoding nested data structures from the flat HTML form-data that’s been submitted by the client, and also a system for generating nested forms.

How Obviel deals with forms

Obviel does several things differently:

  • the form description is in JSON
  • the form contents is maintained as a JSON object by the client
  • the form content JSON is submitted to the server using an AJAX request.

Let’s look at an example first.

Here is an Obviel form:

{
  ifaces: ['viewform'],
  form: {
    widgets: [
      ifaces: ['textlineField'],
      name: 'test',
      title: 'Test',
      validate: {
         required: true
      }
    ],
    controls: [
      {
         'label': 'Submit',
         'action': 'http://example.com/submit'
      }
    ]
  },
  data: {
    'test': 'Some value'
  }
}

If this JSON is assigned to an object form in JavaScript, this is how we would render this form in an element somewhere on the page:

el.render(form);

The form would have one field, test, with the value Some value filled in (from the data object). The form would also have a submit button labeled Submit.

When the user changes the form, the data object will be automatically updated.

The test field is required. This means that a validation error will appear inline if the user attempts to submit the form without filling in this field, and submission will not proceed. Validation is handled on the client side.

Conversion is also performed partially on the client-side: an integerField will convert to a JavaScript number for instance, and a booleanField to a JavaScript true or false value.

Further conversion and validation can be performed on the server-side. Conversion is done to cast a value into one more convenient for the server-side: a date string may be converted into a date object, for instance. Validation after form submission on the server side is entirely restricted to validation for security purposes and not used for feedback purposes: is the JSON structure received actually legitimate considering the constraints of the form? In that case there is either an attempted security breach or an error, and server side form handling should not proceed. Since these situations should not occur in normal usage, there is no mechanism for server-side validation error reporting. (A mechanism for server-assisted client-side inline validation is however provided: a form may have a global validation URL that will validate the data object and return validation errors for it in a JSON structure. This information is then used by the client to supplement the inline validation procedure)

When the user presses the submit button on the form, the data object will be submitted as JSON to the control’s action URL, in this case http://example.com/submit.

Nested and repeating structures come naturally to Obviel forms: a nested field’s data is simply a sub-object of data, and a repeating field’s data is an array of sub-objects.

Error events

When Obviel Forms sets an error message (either field-error or global-error) for a field, or clears such an error message, an event is sent to the element on which the message is set. The event names are:

  • field-error.obviel-forms: a field error is set
  • field-error-clear.obviel-forms: a field error is cleared
  • global-error.obviel-forms: a global error is set
  • global-error-clear.obviel-forms: a global error is cleared

These events bubble up the DOM, so you can bind to these events on a higher level, such as the form or the document. The event object passed to the handler has a target property that can be used to retrieve the element on which the message was set.

Overriding the error area

You can override the way the error area per fields looks by registering a view on the special obvielFormsErrorArea iface. You need to do this after the obviel-forms file has been included. In it you should make sure of creating two elements which can contain text content that have the id this.obj.fieldErrorId and this.obj.globalErrorId, so that the errors can be rendered.