Apache Struts 2 Documentation > Home > Overview > Whiteboard > Developing Ajax Widgets |
This page is intended for framework developers rather than application developers.
The ajax/dhtml components use the DOJO Toolkit for both javascript event handling and AJAX calls.
To understand the widget framework this page is a must read:
http://dojotoolkit.org/docs/fast_widget_authoring.html
To understand the dojo event framework which is used extensively by the widget framework read this:
http://dojotoolkit.org/docs/dojo_event_system.html
OK Great so your smart on DOJO Widgets and DOJO Events lets see how we use these.
Lets start with looking at what a user of WW would include in their page, a JSP in this case:
<saf:a id="link1" theme="ajax" href="/AjaxRemoteLink.action" showErrorTransportText="true" errorText="An Error ocurred">Update</ww:a>
This is just a standard framework component. All the attributes defined here must map to a component class thats defined in the taglib.tld. Were not going to go into how the componets work in this discussion, just be assured that nothing different happens here.
The framework via the component system will read in the ajax/a.ftl file to determine how to generate the following html file. Again this is standard Component processing so we'll breeze over this.
Now lets look at what this snippet of code would generate for us in html:
<a dojoType="BindAnchor" evalResult="true" id="link1" href="/ajax/AjaxRemoteLink.action" errorHtml="An Error ocurred" showTransportError="true">Update</a>
Lets review this file. The dojoType type tells the dojo parser what to do with this tag. This is going to need to correspont to a call in our widge file like:
dojo.widget.tags.addParseTreeHandler("dojo:BindAnchor");
All the other attributes are basically passthrough from our component code to our widget code. No real magic happening w/ them.
Next up lets look at some snippets of the widget file:
webwork.widgets.HTMLBindAnchor = function() { //lots removed for clarity this.widgetType = "BindAnchor"; this.templatePath = dojo.uri.dojoUri("webwork/widgets/BindAnchor.html"); // the template anchor instance this.anchor = null; //lots removed self.anchor.href = "javascript:{}"; dojo.event.kwConnect({ srcObj: self.anchor, srcFunc: "onclick", adviceObj: self, adviceFunc: "bind", adviceType: 'before' }); //snippet removed } } // make it a tag dojo.widget.tags.addParseTreeHandler("dojo:BindAnchor");
There are three aspects in this code snippet that are worth review. The declaration of the templatePath. This defines to DOJO where the prototype for its component lives. DOJO is going to read this component to determine what event binding needs to happen (TODO: a better description here). Were going to look at this template file in a moment, this file is where the real magic happens. The second aspect of this file is the kwConnect call... this is the ajax call to the remote source. I removed the snippet that happens afterwards but its not important here. And the final aspect worth understanding now is the last line. This tells dojo that this widget is registered as the name BindAchor... recall the dojoType="BindAnchor" in the above HTML snippet.
Now lets review the template file... BindAnchor.html... Understanding the template files were the big realization moment for me.
<a dojoAttachPoint="anchor"></a>
This template simply tells dojo one thing. the dojoAttachPoint. This attribute dojoAttachPoint is the javascript variable in the widget file to attach thid DOM object to. If you review the above widget code you will see a variable declaration called this.anchor = null; Dojo will plug this DOM object into that variable so its availabe in the widget JS. COOL.
OK... lets look at a more complex template file.
<input dojoAttachPoint="attachBtn" dojoAttachEvent="onClick: bind" type="submit" />
This is the code for the button template. Again its got the dojoAttachPoint attribute, but its also got dojoAttachEvent. This is based on the DOJO event system. the dojoAttachEvent property gives us a mapping between what the DOM Node's event name is (onClick) and what logical action to take as a result (bind). This is how the the dojo widget code itercepts the button click code and calls the bind function.
Ok so now you can see how dojo intercepts calls to the real button click, and calls the bind funciton in your widget code. You could do most anything in this method. But in this case the bind function is defined in Bind.js which is the super JS inherited file to BindButton.js.
Hopefully this combined with the DOJO references is enough to get you up to speed.