Survey Form with Validation

Posted on

Form is one of the key elements of a web application. It enables the communication and interaction between the users and a website. However, it is also a major channel of attacking a web site as I mentioned in my earlier blog post Web Application Security. Although it is not enough to secure a website by validating and sanitizing user input in the front-end, validation for a form can detect unintentional human mistakes and reduce invalid calls to the server. In this blog post, I will explain a few form validation methods using dojo form widgets.

The most common web forms are for managing a user account, leaving a message or conducting a survey. In this post, we will use a survey form for example. Let’s take a look at the form below and spend a few minutes to think about how you can validate the user input in different specific fields.

a blank form

Since a valid name only include letters, spaces, and sometimes dash, the validation can be done by a simple regexp expression and specify it with the regExp property of the ValidationTextBox. ValidationTextBox checks user input as they type and show error message if needed.

// code for name input field
<label for="name">Name*: </label>
  <input id="name" type="text" name="name" 
         data-dojo-type="dijit.form.ValidationTextBox"
         data-dojo-props="regExp:'^[- A-Za-z]+$',
         required:true, trim:'true', maxlength:64"/>

Age input field is a drop down menu which is good for security as well as usability. It provides options for user to choose from and the options can be only those interested ones. Since the value for each option is set, nothing much needs to be done in the front-end. The value of form does not contain most of the advanced form widgets and this rating widgets is one of them, thus you will need to get the values for those fields individually and mix in with the rest of the form data when submitting the form.

Besides using regexp to validate the input, you can take advantage of the predefined validate functions in dojox/validate.

// code for email input field
<label for="email">Email*: </label>
<input id="email" type="text" name="email" data-dojo-attach-point="email" 
    data-dojo-type="dijit.form.ValidationTextBox"
    data-dojo-props="required:true, invalidMessage:'Invalid Email address', 
    trim:'true', maxLength:32"/>

The rating field is one of dojox form widgets where you can specify number of stars and default value. Same with other textbox input, I used a customized regexp to validate the reference # field. SimpleTextArea widget lets you specify the rows and cols for the text area while TextArea widget will display a text box and change the size as the user types in more data.

// set validator for reference # field
_setValidator: function _setValidator(){
    this.refNum.validator = function(value){
        return value== "" || /^[s-zS-Z][a-hA-H][0-9]{6}$/.test(value);
    };
}

// strip off invalid characters in textarea
_cleanString: function _cleanString(text){
    return text.match(/[^<>\\]?/g).join("");
}

Last but not least, connecting events with the submit button.

on(this.submitBtn, "click", lang.hitch(this, function(){
    var rating = this.rating.get("value"),
	    commentText = this._cleanString(this.comment.value);

    if(this.form.validate() && rating !== 0){
        response = "Form data in json format:<br/>";
        response += json.stringify(lang.mixin(this.form.get("value"), 
            {comment:commentText, rating:rating}));
    }
    else{
        response = "Form can not be submitted.<br/>";
        response += "Please fill in all required field and verify the data 
            you have entered.";
    }
    this.formDataDiv.innerHTML = response;
}));

Check out the Demo.


Dojo On Module

Posted on

Starting from Dojo 1.7, dojo.connect is deprecated and replaced by dojo/on and dojo/aspect. While dojo.connect provides cross-browser capability to manipulate events for dom nodes, the biggest disadvantage is that you can only connect/disconnect one event type at a time even if they have the same event handler. The new dojo/on module came out to address this issue.

The basic syntax for adding event handler for multiple event types is:

on(targetObject, events, eventHandler);

For example:

define(["dojo/on, dojo/touch"], function(on){
    var clickImage = on (this.image, "click, touch.press", this.clickImageHandler);
    //to disconnect the event
    clickImage.remove()
}

You can further refine the target object by adding css class selector to the events parameter. However, this feature does not apply to extension events defined in dojo/gesture and dojo/mouse.
For example, you want to trigger the event only when users single click on an image or double-click on an image if it has class smallImage.

define(["dojo/on"], function(on){
    var clickImage = on (this.image, "click, .smallImage:dbclick", 
            this.clickImageHandler);
}

Another useful use case of dojo/on is to apply on a node list returned by dojo/query. For example:

define(["dojo/on, dojo/query"], function(on,query){
    var clickImage = query(".banner").on("click, .smallImage:dbclick", 
            this.clickImageHandler);
}

Dojo/on module also comes with other some functions for more advanced usage:
on.selector – apply event delegation for extension events
on.emit – return a normalized event object
on.pausable – return a an event object with pause function
on.once – return an event object will self destroy after being called once