Monday, August 19, 2013

DGrid data refreshing event?

I'm working on dojo chart generation based on the data from dojo dgrid. 
The logic I'm building is as follows: 
1. Subscribe to a topic in the main page: 
connect.subscribe("dgridrefresh", mModule.generateRestChart); 
2. Initiate a JsonRest datastore. Use the datastore to create a dgrid with pagination plugin. 
3. Start the dgrid in some contentpane. 
4. Publish an event to a topic upon "dgrid-refresh-complete" event. 
The code is as follows (topicname is the paramter): 
dgrid.on("dgrid-refresh-complete", function(event) { 
                                console.log("refresh-complete. Publishing to " + topicname); 
                                require(["dojo/_base/connect"], function(connect) { 
                                        connect.publish(topicname, [event]); 
                                }); 
                        }); 

However, I observed that mModule.generateRestChart() function was only invoked once when the dgrid was initiated. I expect the method being called whenever pagination is executed. 

Same information is here:http://dojo-toolkit.33424.n3.nabble.com/get-data-refresh-notification-from-dgrid-with-jsonrest-datastore-td3998670.html

In the end, it turned out the dgrid-refresh-complete event will only be emitted once when dgrid is refreshed with loading the first page of data.
I did a workaround by customizing the pagination plugin for dgrid. The change I made was pretty simple: inside the Deferred block of gotoPage method of dgrid.extensions.Pagination, I added another emit of dgrid-navigation-complete event, which is a customized event by myself.

pointcuts before and after an ajax call in dojo?

I've been struggling in searching for proper pointcuts for dojo ajax calls.
The problem is that I'm using JsonRest with DGrid and pagination plugin -- actually it's not a "problem" because I chose to do so in order to shorten the development cycle for core frontend functionality. However, this combination doesn't offer the solution to several minor issues. For example, I want to show a loading picture, instead of just a loading message.
I decided to use aspect advice functions, which is a great piece of functionality available after dojo 1.7. It's not so easy to find the pointcuts to define advices. Reasons are here: http://dojo-toolkit.33424.n3.nabble.com/dojo-aspect-before-function-not-firing-td3985714.html#a3998683 )

In the end, I got some workaround to advise on _create method of dojo/request/xhr. But as I mentioned it's not a nice solution. Hopefully sitepen guru could expose some pointcuts in future releases.

Httpheaders to enable CORS filter for REST service used by dojo jsonrest data store

Dojo jsonrest datastore provides a simple way to implement ajax communication between dojo data grid (datagrid, enhancegrid, dgrid, or ondemandgrid) and the web service provider.
However, most times people would face CORS access issue when using jsonrest api.
Here's a few key points for the server side to enable the connection with jsonrest:
1. Access-Control-Allow-Origin, this header defines the allowed originate json request client. If not set, errors like "origin not allowed" will be thrown.
2. Access-Control-Allow-Headers, this header defines the allowed requesting headers, such as X-Requested-With, X-Range, Range, and so on. If not set, errors like "header not allowed" will be thrown.
3. Access-Control-Expose-Headers, this header defines the allowed response headers, such as Content-Range. If not set, error like "refused unsafe header" will be thrown.
X-Requested-With, X-Range, Range, Content-Range are the key headers attributes for jsonrest api to communciate with the server. They have to be enabled in the http header.

In order to enable them, we need to add/set a few headers from server side programmatically. Using java servlet/tomcat as an example, we can use server side filter to achieve this.
There's existing CORS filter library available at http://software.dzhuvinov.com/cors-filter-installation.html . However, it didn't work well for me. Implementing a custom CORS filter isn't that difficult as well. Here's the code:
public class CorsFilter implements Filter {

public CorsFilter() { }
public void init(FilterConfig fConfig) throws ServletException { }
public void destroy() { }
public void doFilter(
ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res=(HttpServletResponse)response;
res.addHeader("Access-Control-Allow-Origin", "*");
if(res.getHeader("Access-Control-Allow-Headers")==null) {
res.addHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-Range, Range, Content-Type, Accept");
}else{
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-Range, Range, Content-Type, Accept,"+res.getHeader("Access-Control-Allow-Headers"));
}
res.addHeader("Access-Control-Expose-Headers","Accept-Ranges, Content-Encoding, Content-Length, Content-Range");
chain.doFilter(request, response);
}
}
 After configuring this filter to apply to all requesting paths, it'll for sure enable those dojo jsonrest headers.
Please feel free to comment on whether there's easier ways to do this.

Tuesday, August 06, 2013

customize the format for dojo widgets

Recently I just started the POC on a small reporting tool based on dojo (The major effort is still at the server side - controller & model layer, which sends JSON objects to be presented in the frontend.)
After going through a few documentation on the dojotoolkit website, I still could not find the information how I can customize the look and feel of widget. Good thing about javascript library is that you can always see the code. -- after browsing the contents of the dijit/themes/claro subdirectories, it looks not so difficult for me to find out how to do the customization, because the dojo class names are quite intuitive.
For example, if I'd like to change the style of the accordion title, I can use the following selection in the css file (menuPanel is the container of the accordion in my html file):
#menuPanel .dijitAccordionTitle{
...
}
#menuPanel .dijitAccordionInnerContainerActive .dijitAccordionTitle, #menuPanel .dijitAccordionInnerContainerSelected .dijitAccordionTitle{
...
}
To change the title or tab label for tab container, the following can be used (centerPanel is something from my code, not part of dojo):
#centerPanel .dijitTabChecked {
...
}
#centerPanel .dijitTabContainerTop-tabs{
...
}
Things become easier if you dig a bit more :-)