Online courses in ASP.NET MVC, ASP.NET Core, and Design Patterns conducted by Bipin Joshi. Read more...
Learn ASP.NET MVC / Core, jQuery, Angular, and Design Patterns through our online training programs. Courses conducted by Bipin Joshi on weekends. Read more details here.

Utilize Custom Events in jQuery using on() and trigger()

Handling client side DOM events such as click and keypress is a common task in the jQuery code. The DOM events are always bound to some or the other HTML element. However, there can be situations where you may need to flag some application specific behavior or event. For example, you might be having an Ajax code that periodically checks the server for availability of some data. As soon as the data is made available by the server you may need to notify to your client side code about its availability so that your code can take an appropriate action. Obviously, there is no DOM event that can be used in this case. Luckily, jQuery allows you to define your own events that can be raised from within your code. This article shows how jQuery's on() and trigger() methods can be used for the task just mentioned.

Let's try to use custom events in a sample scenario. Suppose you have an Ajax driven function GetData() that polls the server to check whether data is available or not. Once the data is available you want to update several DOM elements from the page based on the data as well as perform some application specific processing. One way to deal with this situation is to write all the logic in the success handler of $.ajax() method. The following code shows how this can be done:

function GetData()
{
    $.ajax({
        url: "/home/getdata",
        type: "GET",
        contentType: "application/json",
        dataType: "json",
        success: function (data) {
         //...
         //your code here
         //...
        }
    });
}

As you can see, the GetData() client side function calls /Home/GetData action method of Home controller. The success callback function receives the server data and then performs all the required processing. Although this approach works, it has a drawback. All the DOM elements that need to utilize the data must be known to the success handler. The success handler should also know the exact logic to be executed for each DOM element. For example, once the data is receives TextBox1 may want to display that value, Table1 may want to append a row with that data filled in, Div1 may want to display some message to the end user based on that data and so on. Placing all this logic inside the success handler makes it bulky and rigid. What if DOM elements interested in the data received are not known at development time? What if some DOM elements want to utilize or skip the data based on some programmatic condition? Such operations are tedious to code in the above approach.

A better approach is to implement some sort of subscription model for the DOM elements and then once the data is received notify the subscribers about the data arrival. This way the success handler simply contains code to notify the subscribers. Each subscriber deals with the data as per its own requirement. The success handler need not know about the exact DOM elements to update at all. This is where custom events can come handy. Once the data is received from the server the success handler will trigger some custom event to notify the subscribers. The subscribers, in turn, will wire an event handler to that event and utilize the data as per their requirement inside the wired handler.

Let's see how this can be implemented. Consider a simple ASP.NET MVC view:

<form>
    <input type="text" id="text1" />
    <div id="div1"></div>
    <input type="text" id="text2" />
    <br /><br />
    <table id="table1" border="1" cellpadding="5"></table>
</form>

The view contains four elements - text1, text2, div1 and table1. Except text2 all the elements are interested to get notification when the data is received from the server.

Here is the jQuery code that defines the subscriptions:

var subscribers = [];
var pollTime = 4000;

$(document).ready(function () {

    //add subscriber definition
    subscribers.push({
        ElementId: "text1",
        Handler: function (evt, data) {
            $(evt.target).val(data);
        }
    });

    subscribers.push({
        ElementId: "div1",
        Handler: function (evt, data) {
            $(evt.target).html("<h2>" + data + "</h2>");
        }
    });

    subscribers.push({
        ElementId: "table1",
        Handler: function (evt, data) {
            $(evt.target).append("<tr><td>" + data + "</td></tr>");
        }
    });

    //attach event handlers to the subscriber elements
    for (var i = 0; i < subscribers.length; i++) {
        $("#" + subscribers[i].ElementId).
        on("datareceived",subscribers[i].Handler);
    }

    //start Ajax polling
    window.setTimeout(GetData, pollTime);
});

The code begins by declaring two variables - subscribers and pollTime. The subscribers is an array that holds JavaScript objects. Each JavaScript object stored in the subscribers array has two properties namely ElementId and Handler. The ElementId property indicates the ID of the DOM element interested to subscribe to the custom event. The Handler property points to an anonymous function that acts as the event handler. In the above example text1, div1 and table1 are the DOM elements interested in the custom event. Note that all the handlers receive data parameter that supplies the data received from the server. The textbox uses this data to fill itself. The <div> uses this data to display it statically inside <h2></h2> tag. And the table appends that data as a table row.

Now comes the important part. A for loop iterates through the subscribers array. For every array element on() method of jQuery is called to bind datareceived event to the handler. The datareceived is a custom event and you can use any name instead of datareceived. This is how jQuery allows you to handler custom events.

Then setTimeout() method starts the polling operation by specifying GetData() function and pollTime value.

The modified GetData() function looks like this:

function GetData()
{
    $.ajax({
        url: "/home/getdata",
        type: "GET",
        contentType: "application/json",
        dataType: "json",
        success: function (data) {
            for (var i = 0; i < subscribers.length; i++) {
                $("#" + subscribers[i].ElementId)
                .trigger("datareceived", data);
            }
            window.setTimeout(GetData, pollTime);
        }
    });
}

Notice the code marked in bold letters. The success function receives data from the server. A for loop iterates through the subscribers array and for every subscriber trigger() method is called. The trigger() method is used to raise the custom event - datareceived. The data received from the server is passed as the second parameter of the trigger() method.

As you can see, the success callback is quite simple and straightforward now. All it needs is the list of subscribers and it will notify all of them by raising the datareceived event.

The GetData() server side function used in the url parameter above looks like this:

public JsonResult GetData()
{
    return Json(DateTime.Now.ToString("hh:mm:ss tt"),
    JsonRequestBehavior.AllowGet);
}

The GetData() action method simply returns current time in hh:mm:ss format.

If you run the application you should see the datareceived event being handled as expected.

Notice that since text1, div1 and table1 subscribe to the datareceived event, only those elements are updated. The text2 element doesn't subscribe to the datareceived event and hence it is empty.




Bipin Joshi is a software consultant, trainer, author and a yogi having 21+ years of experience in software development. He conducts online courses in ASP.NET MVC / Core, jQuery, AngularJS, and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced Yoga way of life he also teaches Ajapa Meditation to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 09 Mar 2015



Tags : ASP.NET MVC jQuery JavaScript