Skip to main content

Simple end to end jMaki application

Posted by carlavmott on September 11, 2007 at 12:55 PM PDT

This blog describes how to use jMaki actions and events to drive behavior or data in widgets. I will build a simple end to end application that shows the main concepts of widgets driving widgets (behavior) and also getting data from a server when needed.

I actually created two versions of the application, JSP and PHP, for this blog, Each have three Yahoo buttons named 'select CA', 'set Values' and 'reset Values' and one Dojo combobox. The buttons will drive the content of the combobox. In this application, one of the buttons will cause the application to access the server for data which will become the values in the combobox.

The main code of the JSP page looks like:

 <div class="main">
     <div class="leftSidebar">
                   
        <a:widget name="yahoo.button" value="{label : 'select CA',
                     action : {topic : '/combobox/select', message : {targetId : 'bar'}}}"/>
        <a:widget name="yahoo.button" value="{label : 'setValues',
                     action : {topic : '/mytopic/setvalues'}}" />
        <a:widget name="yahoo.button" value="{label : 'resetValues',
                     action : {topic : '/mytopic/resetvalues'}}" />          
     </div> <!-- leftSidebar ->

     <div class="content" style="height:400px">
                   
        <a:widget name="dojo.combobox" subscribe="/combobox"
            value="[
                 {label : 'Alabama', value : 'AL'},
                 {id : 'bar',label : 'California', value : 'CA'},
                 {label : 'New York', value : 'NY', selected : true},
                 {label : 'Texas', value : 'TX'}           
            ]" />

      </div> <!-- content -->
       
  </div> <!-- main -->

The PHP looks like:

<div class="main">
     <div class="leftSidebar">
                   
        < addWidget( array("name" => "yahoo.button", "value"=>"{label : 'select CA',
                     action : {topic : '/combobox/select', message : {targetId : 'bar'}}}"/>
        < addWidget( array("name" => "yahoo.button",
                                     "value" => "{label : 'setValues',
                     action : {topic : '/mytopic/setvalues'}}" />
        <addWidget( array("name" => "yahoo.button",
                                     "value" => "{label : 'resetValues',
                     action : {topic : '/mytopic/resetvalues'}}" />          
     </div> <!-- leftSidebar ->

     <div class="content" style="height:400px">
                   
        < addWidget( array("name" => "dojo.combobox",
                                       "subscribe" => "/combobox",
                                       "value" => "[
                 {label : 'Alabama', value : 'AL'},
                 {id : 'bar',label : 'California', value : 'CA'},
                 {label : 'New York', value : 'NY', selected : true},
                 {label : 'Texas', value : 'TX'}           
            ]" />

      </div> <!-- content -->
       
  </div> <!-- main -->

As an aside, I'd like to point out that the data model for the widgets is the same for the two platforms.

Notice that I used jMaki actions to drive the combobox. We can select a value to be displayed in the combobox by simply publishing an event to a topic along with the id of what we want selected. In jMaki, we use publish and subscribe extensively in widget to widget communication. See my article A practical guide to jMaki events for more information on the publish/subscribe mechanism in jMaki. Let's look at how to use actions more closely.

In the first button, we want to select one of the items, California, in the combobox. To get the desired result, we use the action property to publish to a topic. The combobox implements the jMaki combobox data model which means it implements the data model and two handlers, select and setValues. This means that there is code in the widget wrapper that is called when an event is published to /dojo/combobox/select and /dojo/combobox/setValues. You have the option to override the topic name if you like. In this example I have overwritten the default topic to be /combobox. Now to select the item 'California' all I need to do is send an event to the appropriate topic with the id of the item I want selected. As you can see in the combobox tag above I used the id 'bar' in the second item. I pass that same id as the targetId property in the action object. An event is published to the '/combobox/select' topic along with a payload containing a value object with the value to be selected. The underlying widget initialization code takes care of executing the appropriate code needed to select the item. That's right, you didn't have to write any JavaScript code at all. We believe that simple operations should be just that simple.

In the case of selecting which item will be displayed in the combobox we had all the data that we needed. Some times however, you may want to get data from a data base and so you will need to write a handler to do that. The second button causes the application to make a call back to the server to get data and replaces the values in the combobox with that new data. In that action object I simple have a topic property where I have specified a new topic name and that's all. This means that an event is published to that new topic. I then need to add a handler which will provide the appropriate code which is associated with that topic. To do that I add JavaScript code in the glue.js file which the framework automatically loads with each page. To associate my new handler to the topic that the action object is publishing to I use the jmaki.subscribe function. See the code below:

jmaki.subscribe("/mytopic/setvalues", function (args) {

   jmaki.doAjax({method: "POST",
               url: "data.jsp" ,
                callback: function(_req) {
                    var tmp = _req.responseText;
                    var obj = eval ("(" + tmp + ")");
                    jmaki.publish("/combobox/setValues",  obj );
                    // handle any errors
                }
   });

});

All I have to do is use the same string in both the topic property and the jmaki.subscribe function and the handler will get called.

Once in my handler, I use the jmaki.doAjax call to connect to the server code. This function is a generalized XMLHttpRequest call which can be used from evaluated code. jmaki.doAjax also allows you to set a timeout which will abort the call to the server if exceeded, it encodes any content before contacting the server and it provides some basic error handling.

In this application the server code simply returns the data in JSON format.
For the purpose of this blog I created a JSP and PHP file that contained the data to be returned. Note that the filename in the jmaki.doAjax call must match the name of the file you created. I do have to convert the data returned to a JSON object because what is returned is a string so here I used the eval function and then publish that object as the payload to another topic. By publishing the data to the '/combobox/setValue' topic I have sent the data that I want loaded in the combobox to the widget because it is already subscribed to that topic.

The contents of data.jsp or data.php follows:

[ {  label: "Taipei, Taiwan ", value: "Taipei, Taiwan" , selected: true } , 
{  label: "Shanghai, China", value: "Shanghai, China" },
{ label: "Rome, Italy", value: "Rome, Italy"},
{ label: "Paris, France", value: "Paris, France"}]

For completeness I have include the handler code for the reset button. I used an action to call another handler but I didn't access the serve r to get the data as it included in the handler code itself.

jmaki.subscribe("/mytopic/resetvalues", function(args) {
var list = [
       {label : 'Alabama', value : 'AL'},
       {id : 'bar',label : 'California', value : 'CA'},
       {label : 'New York', value : 'NY', selected : true},
       {label : 'Texas', value : 'TX'}           
    ];
  jmaki.publish("/combobox/setValues",  list );
});

As you can see using jMaki actions simplifies the communication between widgets. Something that I didn't show in this blog is calling multiple actions at one time. You also have the option to specify an array of action objects so that multiple events are fired with just one click. One final note, it is also possible to chain actions. I can specify an action which in turn causes another action to be executed. An example would be a button could drive the selection of a combobox which in turn can drive another combobox. It is quite easy to build an interactive web application using jMaki.

Related Topics >>