AJAX with Yahoo UI components and DWR

I’ve been playing lately with YUI, the Yahoo User Interface library. So far I’ve used the autocomplete and treeview components, and I have to say they are quite easy to use and very complete. I had used Script.aculo.us autocomplete before, but YUI autocomplete has a lot of configuraiton options and all of them really well documented, like caching or being able to easily use it as a normal dropdown when the user just clicks on the field without typing anything. Event handling is also pretty easy.

DWR in the other side is a really easy way to expose your service interfaces through javascript. It is included in Appfuse if you want to see examples.

This is an example configuration that uses Spring to get the myService bean and exposes its getEmployeesByPartialName method. You can also use DWR with Spring namespaces from Spring version 2


<dwr>
  <allow>
    <create creator="spring" javascript="MyService">
      <param name="class" value="com.acme.MyService" />
      <param name="beanName" value="myService" />
      <include method="getEmployeesByPartialName"/>
      <convert converter="bean" match="com.acme.Employee"/>
    </create>
  </allow>
</dwr>

Cool, isn’t it? now prepare to be scared. If you expose a method in your service through javascript users can do all kinds of nasty things. If the user needs to be logged in, not too bad, but still you will most likely need some security framework that can secure java objects and not just http request. Spring Security AKA Acegi can do that using the AOP MethodInvocation interceptor, you just need to configure what permissions needs each method.

A tricky part was integrating YUI with DWR, at least for me that haven’t done much javascript in my life. Here you can see how the html looks like for a employees dropdown that lists the ones that match what you type in the input box, querying the service for the values. The values received can be any object, not just strings, in populateArray you can see how the values to display and the ids are stored for later retrieval.

<input type="text" id="employeeList" />
<div id="employeeListAutocomplete" class="autocomplete"></div>
<script type="text/javascript">
     <!-- populate suggestions array -->  
     function populateArray(dataFromServer, dataFromBrowser){
      for (var i = 0; i < dataFromServer.length; i++) {
       <!-- each employee object has a firstName and lastName property -->
       dataFromBrowser.push([dataFromServer[i].firstName + ' ' + dataFromServer[i].lastName, dataFromServer[i].partyId]);
      }  
     }  
       
     <!-- call dwr remote method and returns suggestions --> 
     function getEmployees(sQuery){
      var aResults = [];
      var callbackProxy = function(results){
          populateArray(results, aResults); 
      }; 

      <!-- disable async req ! --> 
      var callMetaData = { callback:callbackProxy, async:false}; 
      <!-- Call remote method --> 
      MyService.getEmployeesByPartialName(sQuery, callMetaData); 

      return aResults; 
     }

    var managerAutoComp;

    YAHOO.example.ACJSFunction = new function(){
        <!-- Instantiate JS Function DataSource -->
        this.employeesDS = new YAHOO.widget.DS_JSFunction(getEmployees);
        this.employeesDS.maxCacheEntries = 50;
   
        <!-- Instantiate Employee AutoComplete -->
        this.employeeAutoComp = new YAHOO.widget.AutoComplete('employeeList','employeeListAutocomplete', this.employeesDS);
        this.employeeAutoComp.minQueryLength = 0;
        this.employeeAutoComp.maxResultsDisplayed = 50;
        this.employeeAutoComp.prehighlightClassName = "yui-ac-prehighlight";
        this.employeeAutoComp.useShadow = true;

        <!-- autocomplete on employee field focus without typing anything -->
        this.employeeAutoComp.textboxFocusEvent.subscribe(function(){
            var sInputValue = YAHOO.util.Dom.get('employeeList').value;
            if(sInputValue.length === 0) {
                var oSelf = this;
                setTimeout(function(){oSelf.sendQuery("");},0);
            }
        });

        <!-- handler for employee selections -->
        this.employeeAutoComp.itemSelectEvent.subscribe(function(sType, aArgs){
            var aData = aArgs[2]; <!-- array of the data for the item as returned by the DataSource [value,id] -->
            var selectedId = aData[1];
            alert('you have selected id: ' + selectedId);
        });

        <!-- Preload content in the container
        this.employeeAutoComp.sendQuery("");
        -->
    };
</script> 

Happy AJAX coding!

Update: fixed the code listing, I hate Roller!

7 thoughts on “AJAX with Yahoo UI components and DWR

  1. Hi ,

    Can you please let me know where is sQuery is declared and what type of value it will take .

    Regards,
    Ashish

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s