tag:blogger.com,1999:blog-61895283308141143962024-03-06T00:49:15.303-05:00The Wicket EvangelistMy blog on everything WicketJeff Schwartzhttp://www.blogger.com/profile/02747605277666816054noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-6189528330814114396.post-68205626032746255312012-02-05T11:59:00.000-05:002012-02-06T19:34:27.252-05:00Taking The New Wicket Plugin For Netbeans For A Test Ride<div>
<div>
<div>
<div>
<div>
I was very, very pleased and happy to read Geertjan's <a href="http://blogs.oracle.com/geertjan/entry/wicket_1_5_3_in" target="_blank">blog entry</a> announcing his updated and shall I dare say modern (my words, of course) Wicket Plugin for Netbeans v7.1. Previous versions of the Wicket Plugin were tied to the Wicket libraries that were included within the plugin's nbm files. Whenever you created a new Wicket project the plugin would contribute those jars to the new project. If you wanted your project to use a different version of those jars you had to remove the Wicket jars from your project and then add the version of the jars that you preferred. Not that this was a big deal, mind you, but it just seemed, to me at least, that this was an unnecessary built-in dependency.</div>
<div>
<br /></div>
<div>
In this release Geertjan has removed all such dependencies while also improving the plugin's synergy with Netbeans Library Manager. Netbeans allows you to create your own libraries using its Library Manager. The libraries you create are nothing more than named collections of 1 or more jars that when selected are added to your project's class path. When creating a new project the new Wicket plugin will list all libraries that you have created using the Library Manager whose names start with 'wicket'. If you create your own library for Wicket v1.5.3 for example and name it Wicket-1.5.3 then when you create a new Wicket project the plugin will find it and offer it as an option in the Version list of libraries. If you select it from the list the jar files associated with the library will be included in your new project.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCt2koUtH6muLLSS1swNQ5qTRYPSwi3Q3pYFrM84ujqCfBQg9Rnwmnph-cxHbmJCkhytx-z91N38qhBAUxYqzMvI9-P-oNRUXlP1Oomb-DhqbN85DnStLyEIF4sl90sa-jLDGFK001OBIK/s1600/Untitled+2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="442" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCt2koUtH6muLLSS1swNQ5qTRYPSwi3Q3pYFrM84ujqCfBQg9Rnwmnph-cxHbmJCkhytx-z91N38qhBAUxYqzMvI9-P-oNRUXlP1Oomb-DhqbN85DnStLyEIF4sl90sa-jLDGFK001OBIK/s640/Untitled+2.jpg" width="640" /></a></div>
<div>
<br /></div>
<div>
In the above snapshot you can see that in the Version list on the Frameworks page the libraries whose names all start with wicket (case insensitive) are listed as options.</div>
<div>
<br /></div>
<div>
While I have always believed that the Wicket plugin propelled Netbeans to the height of being the preeminent IDE for Wicket development, I am further convinced of that by the release of this latest version of the Wicket Plugin. Great job, Geertjan and might I be so presumptuous as to offer you much thanks, not just from myself but from the Wicket developer community in general, for your continued effort and dedication. Marvelous!</div>
<div>
<br /></div>
</div>
</div>
</div>
</div>Jeff Schwartzhttp://www.blogger.com/profile/02747605277666816054noreply@blogger.com0tag:blogger.com,1999:blog-6189528330814114396.post-80676620304107726642011-12-25T15:17:00.000-05:002012-02-18T09:48:05.006-05:00Merry Christmas And A Happy New Year Message... The Wicket Way<b><span class="Apple-style-span" style="font-family: Verdana, sans-serif; font-size: x-large;">add(new Label("label","Wishing You All A Very Merry Christmas And A Happy New Year!"));</span></b>Jeff Schwartzhttp://www.blogger.com/profile/02747605277666816054noreply@blogger.com2tag:blogger.com,1999:blog-6189528330814114396.post-5840782607355149282011-12-21T02:20:00.000-05:002012-03-08T12:55:11.376-05:00A Reusable jQuery UI Autocomplete Wicket Component<span class="Apple-style-span" style="color: #444444; font-family: Arial; font-size: 13px; line-height: 18px;"><span style="font-family: 'Arial Narrow';">* One in a series of articles on Wicket Interfaces & Methods To Master *</span></span><br />
<br />
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">In my <a href="http://thewicketevangelist.blogspot.com/2011/12/marrying-wicket-and-jquery-ui.html" target="_blank">previous article</a> I demonstrated using Wicket's AbstractAjaxBehavior to integrate with the jQuery UI Autocomplete component. In this article I </span></span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">build upon those concepts to </span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">create a reusable JQueryAutocompleteTextField. If you haven't read my previous article please do so now. Also, this article assumes you know </span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">how to add libraries (jars, libraries, projects) to a project using Netbeans.</span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span><span class="Apple-style-span" style="font-family: Verdana, sans-serif; font-size: x-small;"><b>Note: you may check out read-only working copies of the source for this article anonymously over HTTP:</b></span><br />
<br />
<ul>
<li><b><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">The wicket/jQuery integration library svn checkout - </span></span><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><em>http</em></span></span><span class="Apple-style-span" style="font-size: x-small;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">://wicket-jquery-integration.googlecode.com/svn/trunk/ wicket-jquery-integration-read-only</span></span></b></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif; font-size: x-small;"><b>The demo application svn checkout - http://wicket-jquery-integration-demo-app.googlecode.com/svn/trunk/ wicket-jquery-integration-demo-app-read-only</b></span></li>
</ul>
<br />
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">Wicket provides numerous reusable components and behaviors that makes page composition simple. Any custom components that we develop should be just as easy to use and be as reusable across projects as well. These factors serve as motivation for encapsulating all the logic I presented in <a href="http://thewicketevangelist.blogspot.com/2011/12/marrying-wicket-and-jquery-ui.html" target="_blank">the previous article</a> into a fully self contained reusable component hosted in its own jar file which can be reused in any project just like any one of Wicket's standard components. </span><br />
<br />
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">I will be using <a href="http://www.netbeans.com/" target="_blank">Netbeans</a> v7.0.1 throughout this article. If you aren't using Netbeans along with the <a href="http://plugins.netbeans.org/plugin/3586/wicket-1-4-support" target="_blank">Wicket Plugin</a> for your Wicket development then you aren't using the best IDE available for Wicket development period. This powerful duo provides a level of support for Wicket development that no other IDE can offer. I highly recommend that if you haven't done so already to please download and install Netbeans and then install the Wicket Plugin. You won't regret it, I promise you.</span><br />
<br />
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">This article will be a little more in depth than my previous ones. </span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">So go make yourself a pot of coffee and then lets roll up our sleeves and get on with it then...</span><br />
<br />
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"><b>Objectives And Requirements</b></span><br />
<br />
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">First off, any project worth your effort and time is worth at least minimaly defining its objectives and requirements. Otherwise, how would you know if you are successful or not? So, before we get into the nuts and bolts of the implementation, let us minimally identify the objectives and requirements of the </span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField</span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"> component:</span><br />
<ol>
<li><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">JQueryAutocompleteTextField must fully encapsulate any resources it requires. In the case of our component, the resource is the Javascript code needed for implementation on the client. Therefore the Javascript should be a packaged resource and adapted and rendered along with the markup for the </span></span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField</span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">. User's shouldn't have to write jQuery script to use JQueryAutocompleteTextField.</span></span></li>
<li><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">JQueryAutocompleteTextField should be just as simple to create as i</span></span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">t is to create an out-of-the-box TextField. It also has to be as generic as an out-of-the-box TextField. In the case of JQueryAutocompleteTextField we will extend Wicket's TextField and add our own generic implementation onto that.</span></li>
<li><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField has to be reusable across projects so that means it has to be hosted in its own jar file.</span></li>
</ol>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">With our requirements and objectives now having been stated, lets move onto the project structure we will need in order to create a reusable Wicket component library.</span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><b>Create A Library Project</b></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">As I previously stated above in Objectives And Requirements, item #3, the </span></span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField needs to be hosted in its own jar file. Our goal here is to provide a reusable library. Users of this library will have to include it in their classpath in order to compile their own code and they will also need to have the Wicket jar files on their classpath so that the library can resolve its dependencies on Wicket as well.</span></div>
<div>
<ol>
<li><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">Fire up Netbeans and from the main menu select File | New Project | Java | Java Application and click Next.</span></li>
<li><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">Enter any name you want for the Project Name. I am using WicketJQueryIntegration. If the Use Dedicated Folder for Storing Libraries option is selected, unselect it. Also unselect Create Main Class if it is selected and then click Finish for Netbeans to generate the project.</span></li>
<li><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">Right click on the default src package and select Refactor | Rename and enter any package name you wish to use. I am using com.wicket.jquery.integration.autocomplete.</span></li>
</ol>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">You should now have a project structure that looks this:</span></span></div>
</div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3QiXKt1wLiAWpwaryuizmsLDEZNWfE45_kNT46uErSk664DwSXyNnhO423RMzGBB3CnDZzuwvLch8aj354G1OSWeVihRgT7vyMSNy70wYWw-g_LF4CLN5fZmj4-DGQMC8CrEuxoxCoRES/s1600/Untitled.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="81" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3QiXKt1wLiAWpwaryuizmsLDEZNWfE45_kNT46uErSk664DwSXyNnhO423RMzGBB3CnDZzuwvLch8aj354G1OSWeVihRgT7vyMSNy70wYWw-g_LF4CLN5fZmj4-DGQMC8CrEuxoxCoRES/s400/Untitled.png" width="400" /></a></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">The next thing to do is to add <a href="http://wicket.apache.org/" target="_blank">Wicket</a> 1.5 to our project. If you don't already have Wicket you can go to http://wicket.apache.org/ and download it. I am using version 1.5.3.</span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">WicketJQueryIntegration also requires <a href="http://code.google.com/p/google-gson/" target="_blank">google-gson</a> which you can download if you don't already have it. Add it to the project as well.</span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"><br /></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">With our dependencies added to the project and accounted for we need to do one more thing and that is to insure that the libraries we require for compilation aren't packaged in the jar - it is the responsibility of the users of </span></span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField</span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"> to provide the dependencies on these in their classpath. If we don't do this, then we are building in a level of dependency on the exact same versions of these libraries and we don't want to do that.</span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"><br /></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">Right click on the project node and select Properties and select Packaging. Uncheck the Copy Dependent Libraries option and click OK.</span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"><br /></span></div>
<div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQHw17WiljI0TNnWTZfqYPTkdi0vbhhjtJUz5d4E_2Vdzho6gGB4wIf8dE7skpy5MSdXj_RZtFdlvXuZHVwZ1_6ukZRAgCsx8JsjeCrqtvU7AjunftDC2yNbRuh1cICfXVp_avN3ReAFfi/s1600/Untitled+3.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="158" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQHw17WiljI0TNnWTZfqYPTkdi0vbhhjtJUz5d4E_2Vdzho6gGB4wIf8dE7skpy5MSdXj_RZtFdlvXuZHVwZ1_6ukZRAgCsx8JsjeCrqtvU7AjunftDC2yNbRuh1cICfXVp_avN3ReAFfi/s400/Untitled+3.png" width="400" /></a></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">We now have a project suitable for creating a reusable library that doesn't impose dependencies upon its users and our project structure now looks like this:</span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzbX90UyfhVt8Euiwdkxp4Mvhr8OxlWkS5yZHeqaOcIW72G2X0Q80EGSKlOh3WQLxM63F3XSe9fIxTmidvD2mBols_I1fBsaVDl1oAqCtRTY94k-h5JRyKxt3xMgARf54dPMv8W8wprKjO/s1600/Untitled+4.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="365" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzbX90UyfhVt8Euiwdkxp4Mvhr8OxlWkS5yZHeqaOcIW72G2X0Q80EGSKlOh3WQLxM63F3XSe9fIxTmidvD2mBols_I1fBsaVDl1oAqCtRTY94k-h5JRyKxt3xMgARf54dPMv8W8wprKjO/s400/Untitled+4.png" width="400" /></a></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">Implementing </span></span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField</span></b></div>
<div>
<b><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"><br /></span></b></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">We will begin implementation by creating a subclass of AbstractAjaxBehavior. In my previous article we used an implementation of AbstractAjaxBehavior that was tightly coupled to providing support for selecting states. However, because our goal is to create a reusable implementation, one that isn't tightly coupled to any particular use case, our implementation must therefore provide flexibility, allowing the user to implement their own requirements.</span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">Create a Java class in the com.wicket.jquery.integration.autocomplete package. I named mine AbstractJQueryAutocompleAjaxBehavior. In the editor mark the class as abstract and extend the class from AbstractAjaxBehavior.</span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">The constructor needs to take one parameter, a string whose value is a jQuery selector that identifies the target html text field element that will be used to host the jQuery UI Autocomplete component. Our class also needs a field to store this value:</span></span><br />
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>
public abstract class AbstractJQueryAutocompleAjaxBehavior extends AbstractAjaxBehavior {
// The jQuery selector to be used by the jQuery ready handler that registers the autocomplete behavior
final private String jQuerySelector;
/**
* Constructor
* @param jQuerySelector - a string containing the jQuery selector
* for the target html element (<input type='text'... of the jQuery UI
* Autocomplete component
*/
public AbstractJQueryAutocompleAjaxBehavior(String jQuerySelector) {
super();
this.jQuerySelector = jQuerySelector;
}
</code></pre>
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">As was stated in our Objective And Requirements, item #1, we don't want the users of our component to have to write their own jQuery code to wire up jQuery UI's Autocomplete component and therefore our component must render that code to the client page. Here's the boilerplate javascript that we want to use to render to the client page:</span><br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>$(document).ready(function(){
$('${selector}').autocomplete({
source: function(req, add){
//pass request to server
$.ajax({
url: '${callbackUrl}',
type: 'GET',
cache: false,
data: req,
dataType: 'json',
success: function(json){
var suggestions = [];
//process response
$.each(json, function(i, val){
suggestions.push(val.name);
});
// call autocomplet callback method with results
add(suggestions);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
//alert('error - ' + textStatus);
console.log('error', textStatus, errorThrown);
}
});
}
});
});
</code></pre>
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Create a new Javascript file in the com.wicket.jquery.integration.autocomplete package and name it autocomplete.js. Then copy the code above into it and save the file.</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">We are faced with a slight dilemma because we have no way of knowing which html element the user is going to use. The solution, as implemented, is to allow the user to tell us that by providing a jQuery selector in the constructor that identifies it. But wait, how can we alter the Javascript to use this selector? Well, fortunately for us Wicket makes this kind of easy. Wicket supports modifying packaged resources through a process known as interpolation which just means replacing one thing in the resource with another thing. In Wicket's case the things that need to be replaced are identified by ${...} markers. In each marker we provide a name for the marker. In the above Javascript file we provide for two markers, ${selector} which will be replaced with the jQuery selector provided in the constructor and ${callbackUrl} which will be replaced by the callback url to our Wicket Ajax event handler which we will later implement by overriding onRequest.</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">When we interpolate we provide a HasMap that contains key/value objects. Their keys must match the names we gave each marker and their associated values are what will be used to replace the marker with. When our Javascript resource is contributed to the page it will therefore be rendered with both the jQuery selector and the callback URL. Let's implement that now by overriding the renderHead method of AbstractAjaxBehavior:</span><br />
<div>
<br /></div>
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code> /**
* Contributes a jQuery ready handler that registers autocomplete
* behavior for the html element represented by the selector.
*
* The generation of the ready handler uses interpolation, applying
* the jQuery selector and the variable name of the return call
* back url.
*
* @param component
* @param response
*/
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
Map<String, CharSequence> map = new HashMap<String, CharSequence>(2);
map.put("selector", jQuerySelector);
map.put("callbackUrl", getCallbackUrl());
PackageTextTemplate packageTextTemplate = new PackageTextTemplate(getClass(), "autocomplete.js", "text/javascript");
String resource = packageTextTemplate.asString(map);
response.renderJavaScript(resource, jQuerySelector);
}
</code></pre>
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">In the code above we create a HashMap and add the jQuery selector and callback url to it, the names of which as you can see match those we used in our markers. Additionally, we obtain a PackageTextTemplate resource for the autocomplete.js file which resides in the same package as this class and then we call its asString method passing it the HashMap. asString will interpolate our resource using the HashMap we provided and return the interpolated content of the resource as a String. That solves our slight dilemma quite nicely I think and with very little code.</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Finally we need to actually render the resource to the client page. This is done by calling renderJavaScript, passing it the interpolated resource and the jQuerySelector parameter as a unique id.</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Besides rendering the Javascript we must also handle the actual Ajax callback by overriding the onRequest method. Remember, when we stated our objective and requirements we said in item #2 that the component has to be generic. All that means is that we won't assume how the user intends to use the component. Here is the code for our generic implementation of onRequest :</span><br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code> @Override
public void onRequest() {
Logger logger = LoggerFactory.getLogger(this.getClass());
logger.info("ajax request received");
RequestCycle requestCycle = RequestCycle.get();
Request request = requestCycle.getRequest();
IRequestParameters irp = request.getRequestParameters();
StringValue term = irp.getParameterValue("term");
List<?> matches = getMatches(term.toString());
String json = convertListToJson(matches);
requestCycle.scheduleRequestHandlerAfterCurrent(new TextRequestHandler("application/json", "UTF-8", json));
}
</code></pre>
</div>
</div>
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">In the code above we retrieve the parameter passed to the callback which is the term the user entered into the TextField tied to the jQuery Ui Autocomplete component. We use that term by passing it to an abstract method which we define as follows:</span><br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>public abstract List<?> getMatches(String term);
</code></pre>
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Because we declared this method as abstract it will have to be implemented by the user of AbstractJQueryAutocompleAjaxBehavior which I will get to shortly but this is one way we keep this generic, by deferring implementation of this method. We also keep this generic by defining this method's return value using generics and in our case as a List of some object.</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Finally, onRequest then calls convertListToJson, a method that converts the List of objects returned from the getMatches method to a Javascript array of JSON objects. That array is then returned to the client which will be passed to the success callback method of the Autocomplete component defined in our Javascript.</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Here's the complete code for AbstractJQueryAutocompleAjaxBehavior:</span><br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.wicket.jquery.integration.autocomplete;
import com.google.gson.Gson;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.wicket.Component;
import org.apache.wicket.behavior.AbstractAjaxBehavior;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.request.IRequestParameters;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.handler.TextRequestHandler;
import org.apache.wicket.util.string.StringValue;
import org.apache.wicket.util.template.PackageTextTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author jeffrey
*/
public abstract class AbstractJQueryAutocompleAjaxBehavior extends AbstractAjaxBehavior {
// The jQuery selector to be used by the jQuery ready handler that registers the autocomplete behavior
final private String jQuerySelector;
/**
* Constructor
* @param jQuerySelector - a string containing the jQuery selector
* for the target html element (<input type='text'... of the jQuery UI
* Autocomplete component
*/
public AbstractJQueryAutocompleAjaxBehavior(String jQuerySelector) {
super();
this.jQuerySelector = jQuerySelector;
}
/**
* Contributes a jQuery ready handler that registers autocomplete
* behavior for the html element represented by the selector.
*
* The generation of the ready handler uses interpolation, applying
* the jQuery selector and the variable name of the return call
* back url.
*
* @param component
* @param response
*/
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
Map<String, CharSequence> map = new HashMap<String, CharSequence>(2);
map.put("selector", jQuerySelector);
map.put("callbackUrl", getCallbackUrl());
PackageTextTemplate packageTextTemplate = new PackageTextTemplate(getClass(), "autocomplete.js", "text/javascript");
String resource = packageTextTemplate.asString(map);
String uniqueName = Long.toString(Calendar.getInstance().getTimeInMillis());
response.renderJavaScript(resource, uniqueName);
}
@Override
public void onRequest() {
Logger logger = LoggerFactory.getLogger(this.getClass());
logger.info("ajax request received");
RequestCycle requestCycle = RequestCycle.get();
Request request = requestCycle.getRequest();
IRequestParameters irp = request.getRequestParameters();
StringValue term = irp.getParameterValue("term");
List<?> matches = getMatches(term.toString());
String json = convertListToJson(matches);
requestCycle.scheduleRequestHandlerAfterCurrent(new TextRequestHandler("application/json", "UTF-8", json));
}
public abstract List<?> getMatches(String term);
/*
* Convert List to json object.
*
* Dependency on google-gson library which is
* available at http://code.google.com/p/google-gson/
* and which must be on your classpath when using this
* library.
*/
private String convertListToJson(List<?> matches) {
Gson gson = new Gson();
String json = gson.toJson(matches);
return json;
}
}
</code></pre>
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">All that remains for completing our component's implementation is to implement <span class="Apple-style-span" style="color: #444444; line-height: 18px;">JQueryAutocompleteTextField and this actually is the easiest part to do. Here's the complete code to </span></span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField:</span><br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>package com.wicket.jquery.integration.autocomplete;
import java.util.List;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.IModel;
/**
*
* @author jeffrey
*/
public abstract class JQueryAutoCompleteTextField<T extends Object> extends TextField<T> {
private final String jQuerySelector;
public JQueryAutoCompleteTextField(String id, IModel<T> model, Class<T> type, String jQuerySelector) {
super(id, model, type);
this.jQuerySelector = jQuerySelector;
common();
}
public JQueryAutoCompleteTextField(String id, IModel<T> model, String jQuerySelector) {
super(id, model);
this.jQuerySelector = jQuerySelector;
common();
}
public JQueryAutoCompleteTextField(String id, Class<T> type, String jQuerySelector) {
super(id, type);
this.jQuerySelector = jQuerySelector;
common();
}
public JQueryAutoCompleteTextField(String id, String jQuerySelector) {
super(id);
this.jQuerySelector = jQuerySelector;
common();
}
private void common(){
add(new AbstractJQueryAutocompleAjaxBehavior(jQuerySelector) {
@Override
public List<?> getMatches(String term) {
return JQueryAutoCompleteTextField.this.getMatches(term);
}
});
}
public abstract List<?> getMatches(String term);
}
</code></pre>
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">In the code above we provide numerous constructors allowing the user versatility in how they construct the component. Additionally, each constructor calls the method common which adds an instance of AbstractJQueryAutocompleAjaxBehavior to it. Because in </span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">AbstractJQueryAutocompleAjaxBehavior we declared getMatches as abstract we are here forced to provide for its actual implementation. All our implementation does is call </span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField's getMatches method which is also declared as abstract. By defining this abstract method in </span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField our users will have to provide their own implementation which will depend upon their individual use-cases and fulfills our requirement that this component provide a generic implementation allowing it be used however the user's use-case might dictate.</span><br />
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">That wraps up our implementation of </span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField but a few things remain to be done. First we need to build the jar file so that we can use </span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">JQueryAutocompleteTextField in our Wicket applications and secondly we need to test it. We will cover both beginning with building the jar file.</span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"><br /></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"><b>Building The Jar File</b></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"><br /></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">To build the components jar file right click the project node and select Clean And Build. Netbeans will compile the project and package the component in its own jar file.</span><br />
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;"><br /></span></div>
<div class="separator" style="clear: both;">
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Notice how none of the libraries we are using to build the component are in the jar file - this is because when we created the project we instructed Netbeans not to include them. Users of the component will now be able to use what ever versions of these dependencies they see fit to use.</span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Now all that remains is for us to test our component to make sure that it actually works so lets do that now by creating a small Wicket test application using Netbeans. Make sure you have already installed the <a href="http://plugins.netbeans.org/plugin/3586/wicket-1-4-support" target="_blank">Wicket Plugin</a>.</span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> </span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><b>Testing Our Implementation</b></span></div>
<div>
<ol>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">From Netbeans main menu select File | New Project | Java Web | Web Application which will open the New Project wizard.</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">In the wizard enter any name you like for the test project. I named mine WicketAndJQueryAjax and make sure that the Set As Main Project option is selected. Click Next. </span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Select either GlassFish Server or Apache Tomcat for the server option and click Next.</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">From the list of available Frameworks select Wicket and then click Finish.</span></li>
</ol>
</div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Netbeans will generate a complete Wicket project including the Wicket jars that the Wicket Plugin contributes. Because our component is dependent upon Wicket v1.5 we will have to replace the ones provided by the Wicket Plugin with the 1.5 versions. So remove all the contributed Wicket jars and replace them with those from the 1.5 distribution. Also, add the google-gson jar file to the project as well. </span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">We also need to include our components jar also:</span></div>
<div>
<ol>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Right click on the test project node and select Properties.</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">From the Categories pane select Libraries and click the Add Project button. </span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">In the Add Project window select our components project, WicketJQueryIntegration and click the Add Project Jar Files button.</span></li>
</ol>
</div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">We now want to instruct Netbeans to build our components project when we build our test project:</span></div>
<div>
<ol>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Right click on the test project node and select Properties and select Libraries from the Categories pane in the Project Properties window.</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Select the option Build Required Projects and click the OK button.</span></li>
</ol>
</div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Now, whenever we build out test project, Netbeans will check to see if our components project needs to be rebuilt and will do so first before building our test project.</span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">We won't be using Wicket's markup inheritence in our project since it is quite simple so delete the following files from the com.myapp.wicket package:</span></div>
<div>
<ul>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">BasePage.java</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">BasePage.html</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">FooterPanel.java</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">FooterPanel.html</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">HeaderPanel.java</span></li>
<li><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">HeaderPanel.html</span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"> </span></li>
</ul>
</div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Our test project's structure should now look like this:</span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKQJ0jNBFHs3Z7mBM-8opDllpmrvqy1ol6n9yJhhi0gIYD99aI4jmoHL4P2k8CBaq4eAH1UX3DsHggNgry_rsZu60okOVap9QUWSztOb-OCh8IKbppBzbCB90GXCuo5QEiG_r6uttAFY4E/s1600/Untitled.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKQJ0jNBFHs3Z7mBM-8opDllpmrvqy1ol6n9yJhhi0gIYD99aI4jmoHL4P2k8CBaq4eAH1UX3DsHggNgry_rsZu60okOVap9QUWSztOb-OCh8IKbppBzbCB90GXCuo5QEiG_r6uttAFY4E/s1600/Untitled.png" /></a></div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Our test project will mimic what my previous article did which was to implement an Autocomplete component that allowed the user to select from a list of states that match their input. </span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">O</span><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">pen the HomePage.html file in the editor by double clicking on it. When you do, both it and the HomePage.java file will open. This behavior, one of many, is contributed by the Wicket Plugin.</span></div>
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">With the HomePage.html file now opened in the editor, replace all of its content with the following:</span><br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta charset="UTF-8">
<title>Wicket Example</title>
<link type="text/css" href="css/start/jquery-ui-1.8.16.custom.css" rel="Stylesheet" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.16.custom.min.js"></script>
</head>
<body>
<h1>Marrying Wicket And jQuery UI Auto Complete Ajax</h1>
<h2>jQuery UI Auto Complete State Lookup</h2>
<form class="jqueryid_form2" wicket:id="form1">
US State Lookup: <input class="jqueryid_state" type="text" wicket:id="state"/><br/>
</form>
</body>
</html>
</code></pre>
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Notice that in the above there is no reference to a jQuery UI Autocomplete component, just the normal markup one would expect in any Wicket application. Also notice, there is no jQuery ready handler either. The real magic takes place when the component is rendered by Wicket.</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Now replace all of the contents of HomePage.java with the following:</span><br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>/*
* HomePage.java
*
* Created on December 3, 2011, 10:21 AM
*/
package com.myapp.wicket;
import com.wicket.jquery.integration.autocomplete.JQueryAutoCompleteTextField;
import java.util.ArrayList;
import java.util.List;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.PropertyModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HomePage extends WebPage {
private final Form<HomePage> form1;
private final TextField<String> stateTextField;
private String state = "";
/*
* A State class jsonified into an array and returned to the client
*/
static class State {
State() {
}
State(String name) {
this.name = name;
}
String name;
}
private static class StatesDb {
private static final String[] states = new String[]{
"Alabama",
"Alaska",
"Arizona",
"Arkansas",
"California",
"Colorado",
"Connecticut",
"Delaware",
"Florida",
"Georgia",
"Hawaii",
"Idaho",
"Illinois",
"Indiana",
"Iowa",
"Kansas",
"Kentucky",
"Louisiana",
"Maine",
"Maryland",
"Massachusetts",
"Michigan",
"Minnesota",
"Mississippi",
"Missouri",
"Montana",
"Nebraska",
"Nevada",
"New Hampshire",
"New Jersey",
"New Mexico",
"New York",
"North Carolina",
"North Dakota",
"Ohio",
"Oklahoma",
"Oregon",
"Pennsylvania",
"Rhode Island",
"South Carolina",
"South Dakota",
"Tennessee",
"Texas",
"Utah",
"Vermont",
"Virginia",
"Washington",
"West Virginia",
"Wisconsin",
"Wyoming"
};
static List<State> getStatesLike(String target) {
List<State> matches = new ArrayList<State>();
for (String s : states) {
if (s.toLowerCase().startsWith(target.toLowerCase())) {
State state = new State(s);
matches.add(state);
}
}
return matches;
}
}
public HomePage() { /*
* A private static class for states which supports
* querying for states that are like target and
* returning those in a list.
*/
add(form1 = new Form<HomePage>("form1") {
@Override
protected void onSubmit() {
super.onSubmit();
Logger logger = LoggerFactory.getLogger(this.getClass());
logger.info("The user selected: " + state);
}
});
/*
* A TextField with JQueryAutocompleteBehavior
*/
form1.add(stateTextField = new JQueryAutoCompleteTextField<String>("state",
new PropertyModel<String>(this, "state"), "input.jqueryid_state") {
@Override
public List<?> getMatches(String term) {
List<State> statesLike = StatesDb.getStatesLike(term.toString());
return statesLike;
}
});
}
}
</code></pre>
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Notice in the above that we add a JQueryAutoCompleteTextField to the form and that we also provide our own implementation for its getMatches method allowing us to tailor the component to our specific use case which is to find a list of states that match the value of term.</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Run the project and it should render the following in the browser:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIdO6RDAE6hnc62q5x4OTbuU4T2hoHqg7TqqCxErmfdt3mR4GkyuR43i3VvCDSkspyYZ8FYiWlIIIQrLr1fI5vPJCEcokFd2XKC33J1a_vVH2VDqAu-84JPCHwS-17lAfbhOHJ0DZHk18S/s1600/Untitled.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="143" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIdO6RDAE6hnc62q5x4OTbuU4T2hoHqg7TqqCxErmfdt3mR4GkyuR43i3VvCDSkspyYZ8FYiWlIIIQrLr1fI5vPJCEcokFd2XKC33J1a_vVH2VDqAu-84JPCHwS-17lAfbhOHJ0DZHk18S/s640/Untitled.png" width="640" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Now start slowly typing New York into the text box and as you do will be presented with a list of choice matching what characters you have entered:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE-KWBP00sw9B82sxcZ734z2rV8FjopWSbi5Fbz8PlBxiG0NZgmSlQp2p_zx06ts5qi7scwNpPDWtAoyHwe0ToeDRFYtzj2M6dcfl5_Spv7ceYzJMg62UtXZXaYZnnpwH1oFS6s0RXbA0i/s1600/Screen+Shot+2011-12-21+at+2.43.21+PM.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="210" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE-KWBP00sw9B82sxcZ734z2rV8FjopWSbi5Fbz8PlBxiG0NZgmSlQp2p_zx06ts5qi7scwNpPDWtAoyHwe0ToeDRFYtzj2M6dcfl5_Spv7ceYzJMg62UtXZXaYZnnpwH1oFS6s0RXbA0i/s400/Screen+Shot+2011-12-21+at+2.43.21+PM.png" width="400" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Nice, hey? But wait, there's more. Select one of the suggestions from the list and it will propagate the text box. Once propagated, hit Enter to submit the form and now look at the server's log file and you will see log messages that your selection was submitted with the form.</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Magicians are never supposed to reveal their tricks to the public but browser pages have no such ethics so now let us peek at the markup that was rendered to the client and relate that back to our component:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiHmDEpUb5s7ds9sIRr_cyhSunxcTMepaAXzraXvKFE6WQPVQ7v43tKy3abE2kYM716qeWzgXY2CUFRBszJHyoZWqhyP-PvaqrRP7X1waGoW7f4P27TjTGBbBGo1OHoeztSTWuiLKt5EPH/s1600/Untitled.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="467" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiHmDEpUb5s7ds9sIRr_cyhSunxcTMepaAXzraXvKFE6WQPVQ7v43tKy3abE2kYM716qeWzgXY2CUFRBszJHyoZWqhyP-PvaqrRP7X1waGoW7f4P27TjTGBbBGo1OHoeztSTWuiLKt5EPH/s640/Untitled.png" width="640" /></a></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<div style="text-align: left;">
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span><br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I have highlighted the points of interest in red that relate back to our component. As you can see, the jQuery ready handler itself was contributed and our component tailored it to use the selector we provided it. In addition, it also used the callback url. The success function receives the json object we responded with in our component's onRequest method which had called our getMatches method that we implemented in HomePage.java which returned a List of State objects.</span></div>
<br />
<b><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Summary</span></b><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Wicket v1.5 provides awesome flexibility by allowing easy integration with other component libraries. . The same techniques I used here can be applied in many other cases to create other types of components. The only limits are your imagination so imagine! My imagination tells me that there are many other jQuery UI components just waiting for a similar approach. Hmmm...</span><br />
<br />
<span class="Apple-style-span" style="font-family: Verdana, sans-serif;">I hope you have enjoyed following along with me developing an awesome Wicket/jQuery Ui Autocomplete component. Feel free to leave your comments and please remember to come back soon as I am always cooking something new up to share with you.</span>Jeff Schwartzhttp://www.blogger.com/profile/02747605277666816054noreply@blogger.com8tag:blogger.com,1999:blog-6189528330814114396.post-31395013691522474142011-12-17T13:37:00.000-05:002011-12-19T20:24:15.526-05:00Marrying Wicket And jQuery UI Autocomplete Ajax<span class="Apple-style-span" style="color: #444444; font-family: Arial; font-size: 13px; line-height: 18px;"><strong><span style="font-family: 'Arial Narrow';">* One in a series of articles on Wicket Interfaces & Methods To Master *</span></strong></span><br />
<span class="Apple-style-span" style="color: #444444; font-family: Arial; font-size: 13px; line-height: 18px;"><strong><span style="font-family: 'Arial Narrow';"><br /></span></strong></span><br />
<span class="Apple-style-span" style="color: #444444; line-height: 18px;"></span><br />
<div style="font-family: Verdana, sans-serif; font-size: 13px;">
<span class="Apple-style-span" style="color: #444444; font-family: Arial; font-size: 13px; line-height: 18px;"><strong><span style="font-family: 'Arial Narrow';">Note: the code demonstrated in this article uses the query (v1.6.2) and jquery.ui (v1.8.16) Javascript libraries for client-side scripting and the Google gson library for servers-side JSON support.</span></strong></span></div>
<div style="font-family: Verdana, sans-serif; font-size: 13px;">
<span class="Apple-style-span" style="color: #444444; font-family: Arial; font-size: 13px; line-height: 18px;"><strong><span style="font-family: 'Arial Narrow';"><br /></span></strong></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; line-height: 18px;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Here we pick up from my previous article, Marrying Wicket And jQuery Ajax, but today I will demonstrate how to marry Wicket and jQuery UI, specifically the jQuery UI autocomplete component.</span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; line-height: 18px;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; line-height: 18px;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;">Auto completion allows the user to quickly lookup and select values with minimum key strokes, a fact that has made it a very popular user interface design element. And w</span></span><span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif; line-height: 18px;">hile it is certainly possible to code the javascript necessary to support auto completion by hand, the jQuery UI library provides a very nice implementation and as a bonus you also get all the graphical sugar that the UI provides.</span></div>
<div>
<span class="Apple-style-span" style="color: #444444; line-height: 18px;"><span class="Apple-style-span" style="font-family: Verdana, sans-serif;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">When I began trying to implement this I tried Googling to find out how others have approached this and as a result I learned that no one seemed to have posted a pure Wicket solution but rather relied upon wiQuery's implementation. As I prefer to not use wiQuery and to roll my own reusable "pure" Wicket based solutions I came up with the solution that you will find here in this article which only uses Wicket 1.5 and the jQuery UI library. So lets roll up our sleeves and get on with it...</span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;">Here's the Java code:</span></span><br />
<span class="Apple-style-span" style="color: #444444; font-family: Verdana, sans-serif;"><span class="Apple-style-span" style="line-height: 18px;"><br /></span></span></div>
<div>
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code>/*
* HomePage.java
*
* Created on December 3, 2011, 10:21 AM
*/
package com.myapp.wicket;
import com.google.gson.Gson;
import java.lang.String;
import java.util.ArrayList;
import java.util.List;
import org.apache.wicket.Component;
import org.apache.wicket.behavior.AbstractAjaxBehavior;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.request.IRequestParameters;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.handler.TextRequestHandler;
import org.apache.wicket.util.string.StringValue;
public class HomePage extends WebPage {
private final Form<HomePage> form1;
private final AbstractAjaxBehavior aab1;
private final TextField<String> state;
static class State {
State() {}
State(String name) {
this.name = name;
}
String name;
}
public HomePage() {
add(form1 = new Form<HomePage>("form1"));
form1.add(state = new TextField<String>("state"));
/*
* Ajax Behavior provides an event
* listener as well as the request
* handler.
*/
add(aab1 = new AbstractAjaxBehavior() {
@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.renderJavaScript("var callbackUrl = '" + aab1.getCallbackUrl() + "';", "callbackurl");
}
// handle the ajax request
@Override
public void onRequest() {
System.out.println("ajax request received");
RequestCycle requestCycle = RequestCycle.get();
Request request = requestCycle.getRequest();
IRequestParameters irp = request.getRequestParameters();
StringValue state = irp.getParameterValue("term");
List<State> statesLike = MockDb.getStatesLike(state.toString());
String json = convertListToJson(statesLike);
requestCycle.scheduleRequestHandlerAfterCurrent(new TextRequestHandler("application/json", "UTF-8", json));
}
});
}
/*
* Convert List to json object
*/
private String convertListToJson(List<?> matches) {
Gson gson = new Gson();
String json = gson.toJson(matches);
return json;
}
/*
* A Mock Database
*/
static class MockDb {
private static final String[] states = new String[]{
"Alabama",
"Alaska",
"Arizona",
"Arkansas",
"California",
"Colorado",
"Connecticut",
"Delaware",
"Florida",
"Georgia",
"Hawaii",
"Idaho",
"Illinois",
"Indiana",
"Iowa",
"Kansas",
"Kentucky",
"Louisiana",
"Maine",
"Maryland",
"Massachusetts",
"Michigan",
"Minnesota",
"Mississippi",
"Missouri",
"Montana",
"Nebraska",
"Nevada",
"New Hampshire",
"New Jersey",
"New Mexico",
"New York",
"North Carolina",
"North Dakota",
"Ohio",
"Oklahoma",
"Oregon",
"Pennsylvania",
"Rhode Island",
"South Carolina",
"South Dakota",
"Tennessee",
"Texas",
"Utah",
"Vermont",
"Virginia",
"Washington",
"West Virginia",
"Wisconsin",
"Wyoming"
};
static List<State> getStatesLike(String target) {
List<State> matches = new ArrayList<State>();
for (String s : states) {
if (s.toLowerCase().startsWith(target.toLowerCase())) {
State state = new State(s);
matches.add(state);
}
}
return matches;
}
};
}
</code></pre>
<div>
<br />
In the code above we create an AbstractAjaxBehavior and add it to the page to provide a request handler for the ajax call. Our AbstractAjaxBehavior class overrides two methods:<br />
<br />
<ol>
<li>renderHead, in which we grab the behavior's call back url and contribute it via Javascript to the page where it will be used as the url to call by the jQuery UI autocomplete method.</li>
<li>onRequest, in which we process the ajax request and in which we use the request parameter whose name is 'term' to look up all the states that begin with its value and convert the names of those states to an array of json objects in the form of [{name : "statename"}...]. Finally, we schedule a TextRequestHandler passing that array as a parameter which will be sent back to the client as the result of the ajax call. Note that our response content type is "application/json", "UTF-8". </li>
</ol>
<br />
And that's really all it takes for Wicket v1.5 to support ajax request that must return json. Now, lets take a look at the markup including the Javascript needed to support our integration with jQuery UI and Wicket:<br />
<br />
<pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"><code><!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<meta charset="UTF-8">
<title>Wicket Example</title>
<link type="text/css" href="css/start/jquery-ui-1.8.16.custom.css" rel="Stylesheet" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery-ui-1.8.16.custom.min.js"></script>
<wicket:head>
</wicket:head>
<script type="text/javascript" >
$(document).ready(function(){
$('input.jqueryid_state').autocomplete({source: function(req, add){
//pass request to server
$.ajax({
url: callbackUrl,
type: 'GET',
cache: false,
data: req,
dataType: 'json',
success: function(json){
var suggestions = [];
//process response
$.each(json, function(i, val){
suggestions.push(val.name);
});
// call autocomplet callback method with results
add(suggestions);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
//alert('error - ' + textStatus);
console.log('error', textStatus, errorThrown);
}
});
}});
});
</script>
</head>
<body>
<h1>Marrying Wicket And jQuery Ajax</h1>
<h2>jQuery UI Auto Complete State Lookup</h2>
<form class="jqueryid_form2" wicket:id="form1">
US State Lookup: <input class="jqueryid_state" type="text" wicket:id="state"/><br/>
<div id="statelist"/>
</form>
</body>
</html>
</code></pre>
</div>
</div>
<br />
In the above Javascript code we create a jQuery ready handler which sets up jQuery UI autocomplete. Here we use a json object that contains the property named source and which provides a callback function that autocomplete will call to retrieve the results matching the user's input. In this callback we use jQuery's ajax method to make an ajax call back to the Wicket event listener whose url is stored in the global variable callbackUrl which we obtained from the AbstractAjaxBehavior we created in our Java code.<br />
<br />
Finally, the result from the ajax call, which is an array of json objects whose val properties are the names of the states are passed back to autocomplete by calling the add callback method. jQuery Ui autocomplete uses these to present a list of options to the user as can be seen from the following screen shot:<br />
<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKHMGwyPJgA-eIU3weNbV0tkboEPhGhLU77uO2FuX948GhoxgttVOxVm4fu_M5lJkPDdbmXex5X1nqD11gG5bYB78_gfQEIXCJaPyJFhLE8jlBIW-4TtnU4K_RfZlBSBqelX9lovmbuPQn/s1600/wicketjqueryuiautocomplete.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="385" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKHMGwyPJgA-eIU3weNbV0tkboEPhGhLU77uO2FuX948GhoxgttVOxVm4fu_M5lJkPDdbmXex5X1nqD11gG5bYB78_gfQEIXCJaPyJFhLE8jlBIW-4TtnU4K_RfZlBSBqelX9lovmbuPQn/s640/wicketjqueryuiautocomplete.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
That's pretty impressive I think, especially considering the minimal amount of code we had to write, both on the client and the server. Being able to use this technique along with using Wicket's default Ajax implementation is empowering, allowing us to use the right technologies that best suits the use case.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I hope you enjoyed following along with me and please remember to come back soon because I always have something interesting to write about Wicket.</div>Jeff Schwartzhttp://www.blogger.com/profile/02747605277666816054noreply@blogger.com16tag:blogger.com,1999:blog-6189528330814114396.post-90317070448863798312011-12-04T15:01:00.001-05:002011-12-05T21:04:40.138-05:00Marrying Wicket And jQuery Ajax<div>
<div>
<div style="font-family: Verdana, sans-serif;">
<span class="Apple-style-span" style="color: #444444; font-family: Arial; font-size: 13px; line-height: 18px;"><strong><span style="font-family: 'Arial Narrow';">* One in a series of articles on Wicket Interfaces & Methods To Master *</span></strong></span></div>
<div style="font-family: Verdana, sans-serif;">
<span class="Apple-style-span" style="color: #444444; font-family: Arial; font-size: 13px; line-height: 18px;"><strong><span style="font-family: 'Arial Narrow';"><br /></span></strong></span></div>
<div style="font-family: Verdana, sans-serif;">
<span class="Apple-style-span" style="color: #444444; font-family: Arial; font-size: 13px; line-height: 18px;"><strong><span style="font-family: 'Arial Narrow';">Note: the code demonstrated in this article uses the jquery and jquery.form Javascript libraries for client-side scripting and the Google gson library for servers-side JSON support.</span></strong></span></div>
<div style="font-family: Verdana, sans-serif;">
<span class="Apple-style-span" style="color: #444444; font-family: Arial; font-size: 13px; line-height: 18px;"><strong><span style="font-family: 'Arial Narrow';"><br /></span></strong></span></div>
<div style="font-family: Verdana, sans-serif;">
One of the pleasures of working with Wicket is how easy it makes doing Ajax based DOM replacement. Wicket Ajax wires up an event listener and ties it to a DOM event such as on click, keyup, etc., and upon receipt of the Ajax request hands off an AjaxTarget to an event handler. In the event handler you have access to any form input values with which you can update a database record and update the page by adding components to the AjaxTarget.</div>
</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
Sometimes, though, a Web page requires some Ajax processing that doesn't neatly fit into the mold which Wicket provides out of the box. For instance, one friction point with Wicket is integration with jQuery's Ajax implementation. jQuery is the preeminent Javascript framework and for good reason: it makes doing the hard stuff easy including initiating Ajax requests based on the user actions on the page.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
What then, does it take to marry (so to speak) the strengths of both jQuery and Wicket and benefit from their combined use as far as Ajax is concerned? Well, as I will show you, it isn't hard at all and in fact it is quite easy! Ok, so lets get started.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
Note: For the two examples I am presenting here I am using the latest version of jQuery as well as the jQuery Form plugin. For example 2 I am also using the Google gson library which provides excellent JSON functionality and which is very easy to use. </div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
The first example demonstrates how to use jQuery and the jQuery Form plugin to submit a form via Ajax and how to wire up Wicket to process the request as well as send back a response. Here, the user enters their first and last name and clicks the form's submit button which causes the form to be submitted via Ajax and a response sent back to the client from Wicket which mirrors their input. The key point to take away from this example is the use of Wicket's AbstractAjaxBehavior to create an event listener as well as an event handler which packages a response back to the client.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
The second example demonstrates how to use jQuery and the jQuery Form plugin to implement a dynamic lookup list which consists of an input field in which the user can type and a dynamically created and displayed list of states that match the user's input. As with the first example, the key point to take away from this example is the use of Wicket's AbstractAjaxBehavior.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
In both examples, client side Javascript using jQuery is responsible for the heavy lifting meaning it is the client code that wires up the events that initiate the Ajax responses and not Wicket. This is one clear difference in implementations between the way Wicket does Ajax and the way Ajax is done using client side code.<br />
<br />
The following Java and Markup/Javascript code is for both examples, 1 and 2</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
- Java Wicket Code -</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/*</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * HomePage.java</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> *</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * Created on December 3, 2011, 10:21 AM</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> */</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">package com.myapp.wicket;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import com.google.gson.Gson;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import com.sun.tools.internal.jxc.apt.Const;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import java.lang.String;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import java.util.ArrayList;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import java.util.List;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.behavior.AbstractAjaxBehavior;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.markup.ComponentTag;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.markup.html.WebPage;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.markup.html.form.Form;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.markup.html.form.TextField;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.request.IRequestParameters;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.request.Request;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.request.cycle.RequestCycle;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.request.handler.TextRequestHandler;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import org.apache.wicket.util.string.StringValue;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">public class HomePage extends WebPage {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> private Form<homepage> form1;</homepage></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> private final TextField<string> firstName;</string></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> private final TextField<string> lastName;</string></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> private final AbstractAjaxBehavior aab1;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> private final Form<homepage> form2;</homepage></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> private final TextField<string> state;</string></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> private final AbstractAjaxBehavior aab2;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> public HomePage() {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> /* <b>Example 1</b></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * Ajax Behavior provides an event</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * listener as well as the request</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * handler.</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> */</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> add(aab1 = new AbstractAjaxBehavior() {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // handle the ajax request</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> @Override</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> public void onRequest() {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> System.out.println("ajax request received");</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> RequestCycle requestCycle = getComponent().getRequestCycle();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Request request = requestCycle.getRequest();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> IRequestParameters irp = request.getPostParameters();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> StringBuilder sb = new StringBuilder();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> sb.append("firstName: " + irp.getParameterValue("firstName"));</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> sb.append(", ");</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> sb.append("lastName: " + irp.getParameterValue("lastName"));</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> requestCycle.scheduleRequestHandlerAfterCurrent(new TextRequestHandler(sb.toString()));</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> /*</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * A form whose action tag will be set to the </span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * above behavior's call back url.</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> */</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> add(form1 = new Form<homepage>("form1") {</homepage></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // set the form's action tag to the behavior's call back url</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> @Override</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> protected void onComponentTag(ComponentTag tag) {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> super.onComponentTag(tag);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> tag.put("action", aab1.getCallbackUrl());</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> /*</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * Form inputs for first and last name.</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> */</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> form1.add(firstName = new TextField<string>("firstName"));</string></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> form1.add(lastName = new TextField<string>("lastName"));</string></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> /* <b>Example 2</b></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * Ajax Behavior provides an event</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * listener as well as the request</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * handler.</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> */</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> add(aab2 = new AbstractAjaxBehavior() {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> // handle the ajax request</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> @Override</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> public void onRequest() {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> System.out.println("ajax request received");</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> RequestCycle requestCycle = getComponent().getRequestCycle();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Request request = requestCycle.getRequest();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> IRequestParameters irp = request.getPostParameters();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> StringValue state = irp.getParameterValue("state");</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> List<string> statesLike = MockDb.getStatesLike(state.toString());</string></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> requestCycle.scheduleRequestHandlerAfterCurrent(new TextRequestHandler(convertListToJson(statesLike)));</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> add(form2 = new Form<homepage>("form2") {</homepage></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> @Override</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> protected void onComponentTag(ComponentTag tag) {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> super.onComponentTag(tag);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> tag.put("action", aab2.getCallbackUrl());</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> });</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> form2.add(state = new TextField<string>("state"));</string></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> /*</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * Convert List to json object</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> */</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> private String convertListToJson(List matches) {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> Gson gson = new Gson();</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> String json = gson.toJson(matches);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> return json;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> /*</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> * A Mock Database</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> */</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> static class MockDb {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> private static final String[] states = new String[]{</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Alabama",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Alaska",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Arizona",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Arkansas",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "California",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Colorado",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Connecticut",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Delaware",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Florida",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Georgia",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Hawaii",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Idaho",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Illinois",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Indiana",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Iowa",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Kansas",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Kentucky",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Louisiana",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Maine",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Maryland",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Massachusetts",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Michigan",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Minnesota",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Mississippi",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Missouri",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Montana",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Nebraska",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Nevada",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "New Hampshire",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "New Jersey",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "New Mexico",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "New York",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "North Carolina",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "North Dakota",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Ohio",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Oklahoma",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Oregon",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Pennsylvania",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Rhode Island",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "South Carolina",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "South Dakota",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Tennessee",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Texas",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Utah",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Vermont",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Virginia",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Washington",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "West Virginia",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Wisconsin",</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> "Wyoming"</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> };</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> static List<string> getStatesLike(String target) {</string></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> List<string> matches = new ArrayList<string>();</string></string></span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> for (String s : states) {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> if (s.toLowerCase().startsWith(target.toLowerCase())) {</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> matches.add(s);</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> return matches;</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> }</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> };</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span><br />
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<br />
<div style="font-family: Verdana, sans-serif;">
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
- Markup And jQuery code -</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
</div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><!DOCTYPE html></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><html xmlns:wicket="http://wicket.apache.org"></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><head></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><meta charset="UTF-8"></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><title>Wicket Example</title></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><script type="text/javascript" src="javascript/jquery.js"></script></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><script type="text/javascript" src="javascript/jquery.form.js"></script></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><script type="text/javascript" ></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$(document).ready(function(){</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/*</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">* jQuery Ajax form submission and Wicket response</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">*/</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$('#clickme').click(function(){</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">// get the form input values</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">// var fName = $('input.jqueryid_firstName').val();</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">// var lName = $('input.jqueryid_lastName').val();</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">// ajax callback to the server using jQuery</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$('form.jqueryid_form1').ajaxSubmit({cache: false, success: function(html){$('#responses').append(html + "<br/>");}});</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">});</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/*</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">* jQuery Ajax lookup dropdown list</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">*/</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$('input.jqueryid_state').keyup(function(){</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">var showStatesJson = function(json){</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">var listDomElement = ""</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$.each(json, function(index, value){</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">if(listDomElement == ""){</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">listDomElement = "<select size=\"5\">";</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">listDomElement += "<option>" + value + "</option>"</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">});</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">if(listDomElement != ""){</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">listDomElement += "</select>";</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$('#statelist').html(listDomElement);</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">};</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">// get the form input values</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">// var target = $(this).val();</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">var options = {</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">dataType: "json",</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">cache: false,</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">success: showStatesJson</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">};</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">if($(this).val() != ""){</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$('form.jqueryid_form2').ajaxSubmit(options);</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}else{</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$('#statelist').html("");</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">}</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">});</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">});</span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"></script></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"></head></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><body></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><h1>Marrying Wicket And jQuery Ajax</h1></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><h2>jQuery Ajax form submission and Wicket response</h2></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><form class="jqueryid_form1" wicket:id="form1"></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">First Name: <input class="jqueryid_firstName" type="text" wicket:id="firstName"/><br/></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Last Name: <input class="jqueryid_lastName" type="text" wicket:id="lastName" /><br/></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"></form></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><button id="clickme">Click Me, Please</button></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><div id="responses"/></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><br /></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><h2>jQuery Ajax lookup dropdown list</h2></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><form class="jqueryid_form2" wicket:id="form2"></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">US State Lookup: <input class="jqueryid_state" type="text" wicket:id="state"/><br/></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><div id="statelist"/></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"></form></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"></body></span></div>
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"></html></span></div>
<div>
</div>
<br />
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
<div style="font-family: Verdana, sans-serif;">
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<b>Example 1 - Submit a form via Ajax</b></div>
</div>
<div style="font-family: Verdana, sans-serif;">
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<br /></div>
</div>
<div style="font-family: Verdana, sans-serif;">
</div>
As the above Wicket code for example 1 shows, what we are doing is adding an AbstractAjaxBehavior to the page and using its callback URL (it points to an event listener which delegates the response to the onRequest method) as the value for the form's action tag which we set by overriding the form's onComponentTag method. The jQuery Form plugin will use the value of the action tag as the URL to call when making the Ajax call. </div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
The really interesting code is inside the AbstractAjaxBehavior's onRequest method which is responsible for handling the request as well as the response back to the client. If you have done similar in Wicket versions prior to v1.5 then you will notice that a lot has changed with v1.5 and is in fact much neater.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
In onRequest we obtain a RequestCycle from the page from which we get the actual Request. From the request we are able to easily obtain the params that were posted from the form which are firstName and lastName and with which we create a string and return that string to the client by using a TextRequestHandler.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
Basically, all onRequest processing will follow a similar model regardless of its use case - get a request, get the params, do something with the params and send back a response.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
The response we are sending back is text and that is why we are using a TextRequestHandler which takes a string parameter representing the text to send back to the client in its constructor.<br />
<br />
The code on the client side for example 1 couldn't be easier. Using common jQuery practices we create a call back function to handle the click event on the form. In the handler for the click event we submit the form via Ajax. The Form plugin has numerous options but here you can see that it requires minimal configuration. I am merely requesting that the response not be cached (IE is notorious in this regard) and passing a callback method to handle the success response from the server which just appends it to the DOM in a div whose id is response.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
As example 1 above demonstrated, the key to marrying jQuery and Wicket is having jQuery call the correct URL on the server which points to a component based event listener and which delegates the event to AbstractAjaxBehavior's onRequest method. This is the glue that binds the 2 sides of the coin so to speak. As we will now see, it is this same glue that allows us to implement something more intricate than simply echoing back the values of a form submit.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
<b>Example 2 - Dynamic Lookup List via Ajax</b></div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
Web 2.0 has brought numerous improvements to the user's experience and Ajax is to thank for that obviously. One of the nicer features is the ways we can use partial input to provide results to the user as in the case of auto complete elements. Let's expand on example 1 above and show how by marrying jQuery and Wicket this is quite easy to implement.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
The use case here is simple: Provide a text box in which the user can type the characters for a US state and provide the user with a list of states that match their input from which they can select one.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
Just as we did for example 1 we are again creating an AbstractAjaxBehavior and overriding its onRequest method. Notice how the code is similar to that in example 1. The only difference is what we do with the params we receive and how we use it to create the response back to the client which in this cases requires JSON. The client is wired to submit the form on every keyup event which will post the content of the text field back to the server. In Wicket we get that value and use it to look up all the states that start with that value which are returned to the client as JSON.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
The client creates an event handler to handle the keyup event on the text field which it uses to obtain the text field's value and issue an Ajax request to the event listener pointed to by the form's action attribute. It processes the returned JSON object by creating a select element along with options which contain the states that match the user's input and adds the select element to the DOM.</div>
<div style="font-family: Verdana, sans-serif;">
<br />
<b>Screen Images Of Examples</b><br />
<b><br /></b><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY8l3uw75FBXXFzs_RGXVlXNBs3w8GZWhpPWQ7quTPHcSEDLAndeHWYoVkN8xUvvsSImGgRlwiObeItZeQgmdgWes5PzDbUabntfw9NeuQm2QSDttNBO1muWIrn461nNzejCPa-Ecfph3z/s1600/Untitled+2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY8l3uw75FBXXFzs_RGXVlXNBs3w8GZWhpPWQ7quTPHcSEDLAndeHWYoVkN8xUvvsSImGgRlwiObeItZeQgmdgWes5PzDbUabntfw9NeuQm2QSDttNBO1muWIrn461nNzejCPa-Ecfph3z/s400/Untitled+2.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Screen Image Of Example 1 and 2 - User hasn't entered anything yet</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSKiUtEWKiaYQsNVgQirlKjR8vifXg59WeiBOOJrnyciMLk3WisPeqnQlgXMSrAqjz8AVSeyXx0c2iwhPyqI_Fzf5D_reQsRTJXSl37vXvxG7WRfTKkPdwIEztD26CjhKbBgljpp_lUdWE/s1600/Untitled.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="275" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSKiUtEWKiaYQsNVgQirlKjR8vifXg59WeiBOOJrnyciMLk3WisPeqnQlgXMSrAqjz8AVSeyXx0c2iwhPyqI_Fzf5D_reQsRTJXSl37vXvxG7WRfTKkPdwIEztD26CjhKbBgljpp_lUdWE/s400/Untitled.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Screen Image Of Example 1 and 2 - User has entered data in both</td></tr>
</tbody></table>
<b><br /></b><br />
<br /></div>
<div style="font-family: Verdana, sans-serif;">
<b>Summary</b></div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
As these examples have demonstrated, marrying jQuery and Wicket to work together isn't rocket science and in fact is quite easy to do. The benefit of this marriage is that you can now easily leverage the strength of each, jQuery and Wicket, to their best advantages; you can now comfortably implement that which is easier to do in either jQuery or Wicket, taking advantage of each of their strengths. The option of having the ability to take advantage of the strengths of each layer in the development stack is an empowering asset.</div>
<div style="font-family: Verdana, sans-serif;">
<br /></div>
<div style="font-family: Verdana, sans-serif;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br /></div>
</div>Jeff Schwartzhttp://www.blogger.com/profile/02747605277666816054noreply@blogger.com5tag:blogger.com,1999:blog-6189528330814114396.post-17983763337291120562011-12-04T14:59:00.001-05:002011-12-04T15:00:25.816-05:00Wicket v1.5Wicket 1.5 has been released and brings numerous changes to the framework which deserves adequate coverage to encourage its adoption. Therefore, henceforth all future articles will be based on v1.5.Jeff Schwartzhttp://www.blogger.com/profile/02747605277666816054noreply@blogger.com0tag:blogger.com,1999:blog-6189528330814114396.post-49765249902773728662011-09-05T08:46:00.000-04:002011-09-17T13:25:09.496-04:00How To Validate And Block Ajax Callbacks<div><font face="Arial"><strong><font face="Arial Narrow">* One in a series of articles on Wicket Interfaces & Methods To Master *<br></font></strong><br>Wicket allows you to easily add Ajax support to Wicket components by adding some concrete subclass of the AbstractAjaxBehavior class to them which ties a Javascript DOM event on the client to an event listener in an AjaxEventBehavior or some subclass of.</font><pre></pre><pre><font face="Arial">For instance, suppose you want to add Ajax support to a Wicket component backing an input text element that supports the DOM onkeyup event. Doing so is easily accomplished using the following markup and Java code fragments:<br></font></pre></div><br /><div>Markup</div><pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <body> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <h1>Default Wicket Ajax</h1><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <form wicket:id="<span style="color: #8b0000">defaultajaximplmentationform</span>"><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: Enter Something <input type="<span style="color: #8b0000">text</span>" wicket:id="<span style="color: #8b0000">enterSomething</span>"/><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: </form><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: <div>You entered: <span <span style="color: #0000ff">class</span>="<span style="color: #8b0000">message</span>" wicket:id="<span style="color: #8b0000">message</span>"/></div><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: </body> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: </pre></pre>Java<br><pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> HomePage extends WebPage {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <span style="color: #0000ff">private</span> Form<HomePage> form;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: <span style="color: #0000ff">private</span> TextField<<span style="color: #0000ff">String</span>> textField;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: <span style="color: #0000ff">private</span> Label message;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: <span style="color: #0000ff">private</span> <span style="color: #0000ff">String</span> enterSomething = "<span style="color: #8b0000"></span>";<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: <span style="color: #0000ff">public</span> HomePage() {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: form = <span style="color: #0000ff">new</span> Form<HomePage>("<span style="color: #8b0000">defaultajaximplmentationform</span>");<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: add(form);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: textField = <span style="color: #0000ff">new</span> TextField<<span style="color: #0000ff">String</span>>("<span style="color: #8b0000">enterSomething</span>", <span style="color: #0000ff">new</span> PropertyModel<<span style="color: #0000ff">String</span>>(this, "<span style="color: #8b0000">enterSomething</span>")); <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: textField.add(<span style="color: #0000ff">new</span> AjaxFormSubmitBehavior("<span style="color: #8b0000">onkeyup</span>") {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: @Override<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: <span style="color: #0000ff">protected</span> void onSubmit(AjaxRequestTarget target) {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: // <span style="color: #0000ff">do</span> something meaningful here <span style="color: #0000ff">like</span> updating the database<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: target.addComponent(message);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: @Override<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: <span style="color: #0000ff">protected</span> void onError(AjaxRequestTarget target) {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: <span style="color: #0000ff">throw</span> <span style="color: #0000ff">new</span> UnsupportedOperationException("<span style="color: #8b0000">Not supported yet.</span>");<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: });<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: form.add(textField);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: message = <span style="color: #0000ff">new</span> Label("<span style="color: #8b0000">message</span>", <span style="color: #0000ff">new</span> PropertyModel<<span style="color: #0000ff">String</span>>(this, "<span style="color: #8b0000">enterSomething</span>"));<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: message.setOutputMarkupId(<span style="color: #0000ff">true</span>);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 28: add(message);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 29: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 30: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 31: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 32: </pre></pre><pre><font face="Arial">Looking at the Java code above we can see that I added an Ajax callback for the Javascript onkeyup event to the textfield component by adding an AjaxFormSubmittingBehavior to it. When rendered the AjaxFormSubmittingBehavior contributes Javascript code to the input element's onkeyup event that submits the form that the input element is a child of. The Javascript that submits the form calls into Wicket's Ajax Javascript library whenever the user presses and releases a key when the input element has the input focus.</font><font face="Arial">Here is what the rendered markup looks like:</font></pre><pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <span style="color: #0000ff"><</span>!DOCTYPE html<span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <span style="color: #0000ff"><</span><span style="color: #800000">html</span> <span style="color: #ff0000">xmlns</span>:<span style="color: #ff0000">wicket</span>=<span style="color: #0000ff">"http://wicket.apache.org"</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: <span style="color: #0000ff"><</span><span style="color: #800000">head</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: <span style="color: #0000ff"><</span><span style="color: #800000">meta</span> <span style="color: #ff0000">charset</span>=<span style="color: #0000ff">"UTF-8"</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: <span style="color: #0000ff"><</span><span style="color: #800000">title</span><span style="color: #0000ff">></span>Wicket Example<span style="color: #0000ff"></</span><span style="color: #800000">title</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: <span style="color: #0000ff"><</span><span style="color: #800000">style</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/css"</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: span.message {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: color: #0000FF;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: <span style="color: #0000ff"></</span><span style="color: #800000">style</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">src</span>=<span style="color: #0000ff">"resources/org.apache.wicket.markup.html.WicketEventReference/wicket-event.js"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span><br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">src</span>=<span style="color: #0000ff">"resources/org.apache.wicket.ajax.WicketAjaxReference/wicket-ajax.js"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span><br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">src</span>=<span style="color: #0000ff">"resources/org.apache.wicket.ajax.AbstractDefaultAjaxBehavior/wicket-ajax-debug.js"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span><br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"wicket-ajax-debug-enable"</span><span style="color: #0000ff">></span><span style="color: #008000"><!--/*--></span><span style="color: #0000ff"><</span>![CDATA[/*<span style="color: #0000ff">></span><span style="color: #008000"><!--*/<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: wicketAjaxDebugEnable=true;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: /*--></span>]]>*/<span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: <br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: <span style="color: #0000ff"></</span><span style="color: #800000">head</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: <span style="color: #0000ff"><</span><span style="color: #800000">body</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: <span style="color: #0000ff"><</span><span style="color: #800000">h1</span><span style="color: #0000ff">></span>Default Wicket Ajax<span style="color: #0000ff"></</span><span style="color: #800000">h1</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: <span style="color: #0000ff"><</span><span style="color: #800000">form</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"defaultajaximplmentationform"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"defaultajaximplmentationform4"</span> <span style="color: #ff0000">method</span>=<span style="color: #0000ff">"post"</span> <span style="color: #ff0000">action</span>=<span style="color: #0000ff">"?wicket:interface=:1:defaultajaximplmentationform::IFormSubmitListener::"</span><span style="color: #0000ff">></span><span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">style</span>=<span style="color: #0000ff">"display:none"</span><span style="color: #0000ff">></span><span style="color: #0000ff"><</span><span style="color: #800000">input</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"hidden"</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"defaultajaximplmentationform4_hf_0"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"defaultajaximplmentationform4_hf_0"</span> <span style="color: #0000ff">/></span><span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: Enter Something <span style="color: #0000ff"><</span><span style="color: #800000">input</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text"</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"enterSomething"</span> <span style="color: #ff0000">value</span>=<span style="color: #0000ff">""</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"enterSomething"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"enterSomething5"</span> <span style="color: #ff0000">onkeyup</span>=<span style="color: #0000ff">"var wcall=wicketSubmitFormById('defaultajaximplmentationform4', '?wicket:interface=:1:defaultajaximplmentationform:enterSomething::IActivePageBehaviorListener:0:&amp;wicket:ignoreIfNotActive=true', null,function() { }.bind(this),function() { }.bind(this), function() {return Wicket.$$(this)&amp;&amp;Wicket.$$('defaultajaximplmentationform4')}.bind(this));;"</span><span style="color: #0000ff">/></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: <span style="color: #0000ff"></</span><span style="color: #800000">form</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: <span style="color: #0000ff"><</span><span style="color: #800000">div</span><span style="color: #0000ff">></span>You entered: <span style="color: #0000ff"><</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span>=<span style="color: #0000ff">"message"</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"message"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"message6"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">span</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: <span style="color: #0000ff"></</span><span style="color: #800000">body</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: <span style="color: #0000ff"></</span><span style="color: #800000">html</span><span style="color: #0000ff">></span> </pre></pre><br /><p>Line 23 in the rendered markup above shows that the AjaxFormSubmittingBehavior added the onkeyup event to the input element. The Javascript code it added to the event is the following:<br><br><font face="Lucida Console">var wcall=wicketSubmitFormById('defaultajaximplmentationform7', '?wicket:interface=:2:defaultajaximplmentationform:enterSomething::IActivePageBehaviorListener:0:&amp;wicket:ignoreIfNotActive=true', null,function() { }.bind(this),function() { }.bind(this), function() {return Wicket.$$(this)&amp;&amp;Wicket.$$('defaultajaximplmentationform7')}.bind(this));;<br></font><br>The Javascript added by AjaxFormSubmittingBehavior calls wicketSubmitFormById which is a method that resides in the wicket-event.js, a Javascript file that was also contributed by AjaxFormSubmittingBehavior to the page.<br><br>All of Wicket's numerous Ajax components and behaviors work similarly which is fine if you don't need to do anything on the client after the DOM event and before the Ajax call back to the server. But suppose you want to perform validation before the Ajax call back to the server and possibly block the call back to the server if validation fails, how can you do this? <br><br>Well, the solution is actually quite easy but poorly documented. Even the holly grail of Wicket books, Wicket In Action, doesn't cover this because it was written before the solution presented here in this article was provided in the Wicket library so many readers of the book are left scratching their heads in confusion.<br><br><strong>Prepending Your Own Javascript To Wicket's Generated Javascript<br><br></strong>The solution requires that you override the <em>getAjaxCallDecorator</em> method defined in AbstractDefaultAjaxBehavior in your own behaviors to return an implementation of IAjaxCallDecorator that prepends the Javascript that Wicket generates with your own Javascript which can do anything that your use case might require such as validation and preventing the Ajax call to the server should the validation fail.<br><br>First, lets take a look at IAjaxCallDecorator:</p><pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <span style="color: #0000ff">public</span> <span style="color: #0000ff">interface</span> IAjaxCallDecorator <span style="color: #0000ff">extends</span> IClusterable<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <span style="color: #008000">/**<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: * Name of javascript variable that will be true if ajax call was made, false otherwise. This<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: * variable is available in the after script only.<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: */</span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">final</span> String WICKET_CALL_RESULT_VAR = "<span style="color: #8b0000">wcall</span>";<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: <span style="color: #008000">/**<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: * Decorates the script that performs the ajax call<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: * <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: * @param script<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: * @return decorated script<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: */</span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: CharSequence decorateScript(CharSequence script);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: <span style="color: #008000">/**<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: * Decorates the onSuccess handler script<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: * <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: * @param script<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: * @return decorated onSuccess handler script<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: */</span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: CharSequence decorateOnSuccessScript(CharSequence script);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: <span style="color: #008000">/**<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: * Decorates the onFailure handler script<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: * <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 28: * @param script<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 29: * @return decorated onFailure handler script<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 30: */</span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 31: CharSequence decorateOnFailureScript(CharSequence script);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 32: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 33: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 34: </pre></pre><br /><p>This interface declares 3 methods that must be implemented, all taking a CharSequence script parameter and returning a CharSequence. The CharSequence script parameter passed to these methods is the Javascript that Wicket generated to call it's Ajax Javascript library and that it assigns as the DOM event handler on the client.<br><br>Wicket provides a convenience class, AjaxCallDecorator, which is an adapter class which provides default implementations for these 3 methods.</p><pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <span style="color: #0000ff">public</span> <span style="color: #0000ff">abstract</span> <span style="color: #0000ff">class</span> AjaxCallDecorator <span style="color: #0000ff">implements</span> IAjaxCallDecorator<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: <span style="color: #008000">/**<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: * <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: */</span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">final</span> <span style="color: #0000ff">long</span> serialVersionUID = 1L;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: <span style="color: #008000">/**<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: * @see org.apache.wicket.ajax.IAjaxCallDecorator#decorateScript(CharSequence)<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: */</span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: <span style="color: #0000ff">public</span> CharSequence decorateScript(CharSequence script)<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: <span style="color: #0000ff">return</span> script;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: <span style="color: #008000">/**<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: * @see org.apache.wicket.ajax.IAjaxCallDecorator#decorateOnSuccessScript(CharSequence)<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: */</span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: <span style="color: #0000ff">public</span> CharSequence decorateOnSuccessScript(CharSequence script)<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: <span style="color: #0000ff">return</span> script;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: <span style="color: #008000">/**<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: * @see org.apache.wicket.ajax.IAjaxCallDecorator#decorateOnFailureScript(CharSequence)<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: */</span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 28: <span style="color: #0000ff">public</span> CharSequence decorateOnFailureScript(CharSequence script)<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 29: {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 30: <span style="color: #0000ff">return</span> script;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 31: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 32: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 33: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 34: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 35: </pre></pre><br /><p>To add Javascript that will call our validation routine and prevent the Ajax call should validation fail is just a matter of implementing the AjaxCallDecorator's decorateScript method and prepending script with our own Javascript which I will discuss next but first lets define a use case and build the implementation around that.<br><br>Our use case is the following:<br><br>Provide a form with an input text field in which the user can enter some text. The validation rules specify that the text the user enters should be at least 3 characters or they shouldn't be allowed to submit the form (via Ajax). <br><br>Now here's the implementation:<br><br><strong>Markup<br><br></strong>The markup we provide is very straight forward. It contains a form with a wicket id of form that has 1 input text element which we give a wicket id of <em>enterSomething</em>. We also provide a button the user can click to submit the form via Ajax which we give a wicket id of <em>submitbutton</em>. When the form is submitted we will echo what the user enters in a label which we have assigned the wicket id of <em>message.<br><br></p><pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <span style="color: #0000ff"><</span>!DOCTYPE html<span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <span style="color: #0000ff"><</span><span style="color: #800000">html</span> <span style="color: #ff0000">xmlns</span>:<span style="color: #ff0000">wicket</span>=<span style="color: #0000ff">"http://wicket.apache.org"</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <span style="color: #0000ff"><</span><span style="color: #800000">head</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: <span style="color: #0000ff"><</span><span style="color: #800000">meta</span> <span style="color: #ff0000">charset</span>=<span style="color: #0000ff">"UTF-8"</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: <span style="color: #0000ff"><</span><span style="color: #800000">title</span><span style="color: #0000ff">></span>Wicket Example<span style="color: #0000ff"></</span><span style="color: #800000">title</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">src</span>=<span style="color: #0000ff">"javascript/jquery.js"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: <span style="color: #0000ff"><</span><span style="color: #800000">style</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/css"</span><span style="color: #0000ff">></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: span.message {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: color: #0000FF;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: <span style="color: #0000ff"></</span><span style="color: #800000">style</span><span style="color: #0000ff">></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: <span style="color: #0000ff"></</span><span style="color: #800000">head</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: <span style="color: #0000ff"><</span><span style="color: #800000">body</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: <span style="color: #0000ff"><</span><span style="color: #800000">h1</span><span style="color: #0000ff">></span>Wicket Ajax With Client-Side Validation Using Script Prepending<span style="color: #0000ff"></</span><span style="color: #800000">h1</span><span style="color: #0000ff">></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: <span style="color: #0000ff"><</span><span style="color: #800000">form</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"form"</span><span style="color: #0000ff">></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: Enter at least 3 characters to call the AJAX callback: <span style="color: #0000ff"><</span><span style="color: #800000">input</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text"</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"enterSomething"</span><span style="color: #0000ff">/></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: <span style="color: #0000ff"></</span><span style="color: #800000">form</span><span style="color: #0000ff">></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: <span style="color: #0000ff"><</span><span style="color: #800000">button</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"submitbutton"</span><span style="color: #0000ff">></span>Submit<span style="color: #0000ff"></</span><span style="color: #800000">button</span><span style="color: #0000ff">></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: <span style="color: #0000ff"><</span><span style="color: #800000">div</span><span style="color: #0000ff">></span>You entered: <span style="color: #0000ff"><</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span>=<span style="color: #0000ff">"message"</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"message"</span><span style="color: #0000ff">/></span><span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: <span style="color: #0000ff"></</span><span style="color: #800000">body</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: <span style="color: #0000ff"></</span><span style="color: #800000">html</span><span style="color: #0000ff">></span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: </pre></pre></em><strong>Java<br><br></strong>On the server side we create the Wicket components corresponding to the markup elements discussed above. The key point here is that for the button I am using Wicket's AjaxSubmitLink component whose implementation adds an AjaxFormSubmitBehavior which will contribute the Javascript code for the click event on the button to submit the form back to the server using Ajax. If you spy the source code for AjaxSubmitLink you'll see that it exposes the AjaxFormSubmitBehavior's getAjaxCallDecorator method which we can override to return our own implementation of IAjaxCallDecorator:<br /><pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> HomePage <span style="color: #0000ff">extends</span> WebPage {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <span style="color: #0000ff">private</span> Form<HomePage> form;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: <span style="color: #0000ff">private</span> TextField<String> textField;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: <span style="color: #0000ff">private</span> Label messageLabel;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: <span style="color: #0000ff">private</span> String message = "<span style="color: #8b0000"></span>";<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: <span style="color: #0000ff">private</span> String enterSomething = "<span style="color: #8b0000"></span>";<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: <span style="color: #0000ff">public</span> HomePage() {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: form = <span style="color: #0000ff">new</span> Form<HomePage>("<span style="color: #8b0000">defaultajaximplmentationform</span>");<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: add(form);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: textField = <span style="color: #0000ff">new</span> TextField<String>("<span style="color: #8b0000">enterSomething</span>", <span style="color: #0000ff">new</span> PropertyModel<String>(<span style="color: #0000ff">this</span>, "<span style="color: #8b0000">enterSomething</span>")); <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: textField.setOutputMarkupId(<span style="color: #0000ff">true</span>);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: textField.add(<span style="color: #0000ff">new</span> PreventFormSubmitOnEnterBehavior());<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: form.add(textField);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: add(<span style="color: #0000ff">new</span> AjaxSubmitLink("<span style="color: #8b0000">submitbutton</span>", form) {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: @Override<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> renderHead(HtmlHeaderContainer container) {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: <span style="color: #0000ff">super</span>.renderHead(container);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: String javascript = "<span style="color: #8b0000">validate = function(){ var inputElement = $('#</span>" + textField.getMarkupId() + "<span style="color: #8b0000">'); if($(inputElement).val().length < 3){ $(inputElement).css('background-color', '#ff0000'); return false; }else{ $(inputElement).css('background-color', '#ffffff'); return true; } }</span>";<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: container.getHeaderResponse().renderJavascript(javascript, "<span style="color: #8b0000">entersomethingvalidation</span>");<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: @Override<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: <span style="color: #0000ff">protected</span> IAjaxCallDecorator getAjaxCallDecorator() {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> AjaxCallDecorator() {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 28: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 29: @Override<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 30: <span style="color: #0000ff">public</span> CharSequence decorateScript(CharSequence script) {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 31: PrependingStringBuffer psb = <span style="color: #0000ff">new</span> PrependingStringBuffer(script.toString());<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 32: psb.prepend("<span style="color: #8b0000">if(validate() == false) return false;</span>");<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 33: <span style="color: #0000ff">return</span> psb.toString();<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 34: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 35: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 36: };<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 37: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 38: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 39: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 40: @Override<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 41: <span style="color: #0000ff">protected</span> <span style="color: #0000ff">void</span> onSubmit(AjaxRequestTarget target, Form<?> form) {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 42: System.out.println("<span style="color: #8b0000">yada yada</span>");<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 43: <span style="color: #008000">// do something meaningful here like updating the database</span><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 44: message = enterSomething;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 45: enterSomething = "<span style="color: #8b0000"></span>";<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 46: target.addComponent(textField);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 47: target.addComponent(messageLabel);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 48: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 49: });<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 50: messageLabel = <span style="color: #0000ff">new</span> Label("<span style="color: #8b0000">message</span>", <span style="color: #0000ff">new</span> PropertyModel<String>(<span style="color: #0000ff">this</span>, "<span style="color: #8b0000">message</span>"));<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 51: messageLabel.setOutputMarkupId(<span style="color: #0000ff">true</span>);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 52: add(messageLabel);<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 53: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 54: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 55: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 56: </pre></pre><br /><p>Above we create an instance of AjaxCallDecorator and we override its decorateScript method to prepend the script parameter with our own Javascript on line 30. We prepend Javascript on line 32 that calls our own Javascript function <em>validate</em> which we contributed to the page in our overriding of the renderHead method on line 19. To prevent the Ajax call back to the server should our validate function return false the prepended Javascript returns false.</p><pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: @Override<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <span style="color: #0000ff">protected</span> IAjaxCallDecorator getAjaxCallDecorator() {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <span style="color: #0000ff">return</span> <span style="color: #0000ff">new</span> AjaxCallDecorator() {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: @Override<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: <span style="color: #0000ff">public</span> CharSequence decorateScript(CharSequence script) {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: PrependingStringBuffer psb = <span style="color: #0000ff">new</span> PrependingStringBuffer(script.toString());<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: psb.prepend("<span style="color: #8b0000">if(validate() == false) return false;</span>");<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: <span style="color: #0000ff">return</span> psb.toString();<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: };<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: }</pre></pre><br /><p>When run the markup for HomePage is rendered as follows:</p><pre style="border-bottom: #cecece 1px solid; border-left: #cecece 1px solid; padding-bottom: 5px; background-color: #fbfbfb; min-height: 40px; padding-left: 5px; width: 650px; padding-right: 5px; overflow: auto; border-top: #cecece 1px solid; border-right: #cecece 1px solid; padding-top: 5px"><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 1: <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 2: <span style="color: #0000ff"><</span>!DOCTYPE html<span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 3: <span style="color: #0000ff"><</span><span style="color: #800000">html</span> <span style="color: #ff0000">xmlns</span>:<span style="color: #ff0000">wicket</span>=<span style="color: #0000ff">"http://wicket.apache.org"</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 4: <span style="color: #0000ff"><</span><span style="color: #800000">head</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 5: <span style="color: #0000ff"><</span><span style="color: #800000">meta</span> <span style="color: #ff0000">charset</span>=<span style="color: #0000ff">"UTF-8"</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 6: <span style="color: #0000ff"><</span><span style="color: #800000">title</span><span style="color: #0000ff">></span>Wicket Example<span style="color: #0000ff"></</span><span style="color: #800000">title</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 7: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">src</span>=<span style="color: #0000ff">"../javascript/jquery.js"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 8: <span style="color: #0000ff"><</span><span style="color: #800000">style</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/css"</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 9: span.message {<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 10: color: #0000FF;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 11: }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 12: <span style="color: #0000ff"></</span><span style="color: #800000">style</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 13: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #0000ff">></span><span style="color: #008000"><!--/*--></span><span style="color: #0000ff"><</span>![CDATA[/*<span style="color: #0000ff">></span><span style="color: #008000"><!--*/<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 14: $(document).ready(function(){$('#enterSomething5').live('keypress', function(e){var c = e.which ? e.which : e.keyCode;if (c == 13) {return false;}});});<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 15: /*--></span>]]>*/<span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 16: <br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 17: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">src</span>=<span style="color: #0000ff">"resources/org.apache.wicket.markup.html.WicketEventReference/wicket-event.js"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span><br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 18: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">src</span>=<span style="color: #0000ff">"resources/org.apache.wicket.ajax.WicketAjaxReference/wicket-ajax.js"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span><br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 19: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">src</span>=<span style="color: #0000ff">"resources/org.apache.wicket.ajax.AbstractDefaultAjaxBehavior/wicket-ajax-debug.js"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span><br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 20: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"wicket-ajax-debug-enable"</span><span style="color: #0000ff">></span><span style="color: #008000"><!--/*--></span><span style="color: #0000ff"><</span>![CDATA[/*<span style="color: #0000ff">></span><span style="color: #008000"><!--*/<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 21: wicketAjaxDebugEnable=true;<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 22: /*--></span>]]>*/<span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 23: <br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 24: <span style="color: #0000ff"><</span><span style="color: #800000">script</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text/javascript"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"entersomethingvalidation"</span><span style="color: #0000ff">></span><span style="color: #008000"><!--/*--></span><span style="color: #0000ff"><</span>![CDATA[/*<span style="color: #0000ff">></span><span style="color: #008000"><!--*/<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 25: validate = function(){ var inputElement = $('#enterSomething5'); if($(inputElement).val().length < 3){ $(inputElement).css('background-color', '#ff0000'); return false; }else{ $(inputElement).css('background-color', '#ffffff'); return true; } }<br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 26: /*--></span>]]>*/<span style="color: #0000ff"></</span><span style="color: #800000">script</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 27: <br /><br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 28: <span style="color: #0000ff"></</span><span style="color: #800000">head</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 29: <span style="color: #0000ff"><</span><span style="color: #800000">body</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 30: <span style="color: #0000ff"><</span><span style="color: #800000">h1</span><span style="color: #0000ff">></span>Wicket Ajax With Client-Side Validation Using Script Prepending<span style="color: #0000ff"></</span><span style="color: #800000">h1</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 31: <span style="color: #0000ff"><</span><span style="color: #800000">form</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"defaultajaximplmentationform"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"defaultajaximplmentationform6"</span> <span style="color: #ff0000">method</span>=<span style="color: #0000ff">"post"</span> <span style="color: #ff0000">action</span>=<span style="color: #0000ff">"?wicket:interface=:1:defaultajaximplmentationform::IFormSubmitListener::"</span><span style="color: #0000ff">></span><span style="color: #0000ff"><</span><span style="color: #800000">div</span> <span style="color: #ff0000">style</span>=<span style="color: #0000ff">"display:none"</span><span style="color: #0000ff">></span><span style="color: #0000ff"><</span><span style="color: #800000">input</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"hidden"</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"defaultajaximplmentationform6_hf_0"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"defaultajaximplmentationform6_hf_0"</span> <span style="color: #0000ff">/></span><span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 32: Enter at least 3 character to call the AJAX callback: <span style="color: #0000ff"><</span><span style="color: #800000">input</span> <span style="color: #ff0000">type</span>=<span style="color: #0000ff">"text"</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"enterSomething"</span> <span style="color: #ff0000">value</span>=<span style="color: #0000ff">""</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"enterSomething"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"enterSomething5"</span><span style="color: #0000ff">/></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 33: <span style="color: #0000ff"></</span><span style="color: #800000">form</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 34: <span style="color: #0000ff"><</span><span style="color: #800000">button</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"submitbutton"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"submitbutton7"</span> <span style="color: #ff0000">onclick</span>=<span style="color: #0000ff">"if(validate() == false) return false;var wcall=wicketSubmitFormById('defaultajaximplmentationform6', '?wicket:interface=:1:submitbutton::IActivePageBehaviorListener:0:&amp;wicket:ignoreIfNotActive=true', 'submitbutton' ,function() { }.bind(this),function() { }.bind(this), function() {return Wicket.$$(this)&amp;&amp;Wicket.$$('defaultajaximplmentationform6')}.bind(this));;; return false;"</span><span style="color: #0000ff">></span>Submit<span style="color: #0000ff"></</span><span style="color: #800000">button</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 35: <span style="color: #0000ff"><</span><span style="color: #800000">div</span><span style="color: #0000ff">></span>You entered: <span style="color: #0000ff"><</span><span style="color: #800000">span</span> <span style="color: #ff0000">class</span>=<span style="color: #0000ff">"message"</span> <span style="color: #ff0000">wicket</span>:<span style="color: #ff0000">id</span>=<span style="color: #0000ff">"message"</span> <span style="color: #ff0000">id</span>=<span style="color: #0000ff">"message8"</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">span</span><span style="color: #0000ff">></span><span style="color: #0000ff"></</span><span style="color: #800000">div</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 36: <span style="color: #0000ff"></</span><span style="color: #800000">body</span><span style="color: #0000ff">></span> <br /></pre><pre style="background-color: #fbfbfb; margin: 0em; width: 100%; font-family: consolas,'Courier New',courier,monospace; font-size: 12px"> 37: <span style="color: #0000ff"></</span><span style="color: #800000">html</span><span style="color: #0000ff">></span> </pre></pre><br /><p>Notice that in the above markup on line 34 that our button's onclick event includes our prepended Javascript. Below is the Javascript we contributed by prepending in bold blue highlight:<br><br><font face="Lucida Console">onclick="<font color="#0000ff"><strong>if(validate() == false) return false;</strong></font>var wcall=wicketSubmitFormById('form6', '?wicket:interface=:1:submitbutton::IActivePageBehaviorListener:0:&amp;wicket:ignoreIfNotActive=true', 'submitbutton' ,function() { }.bind(this),function() { }.bind(this), function() {return Wicket.$$(this)&amp;&amp;Wicket.$$('form6')}.bind(this));;; return false;"<br></font><br>And here's what HomePage looks like when rendered in the browser:</p><br /><p><a href="http://lh5.ggpht.com/-5J3qiDHE_z8/TnTK5XA_OTI/AAAAAAAAAk0/bH1LGR_cB6A/s1600-h/2011-09-17-12h22_233.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2011-09-17 12h22_23" border="0" alt="2011-09-17 12h22_23" src="http://lh3.ggpht.com/-9f-fEOwUKtg/TnTK6HBSM7I/AAAAAAAAAk4/qNHCprrrKYo/2011-09-17-12h22_23_thumb1.png?imgmax=800" width="644" height="330"></a></p><br /><p>If you enter 2 characters or less and then click the submit button you will see the following:</p><br /><p><a href="http://lh5.ggpht.com/-3wVxiGMtLf8/TnTK6kHG2HI/AAAAAAAAAk8/Q0DkcYKESRo/s1600-h/2011-09-17-12h25_313.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2011-09-17 12h25_31" border="0" alt="2011-09-17 12h25_31" src="http://lh3.ggpht.com/-Espqlv57FrI/TnTK7ACSonI/AAAAAAAAAlA/uL1mTuyywPs/2011-09-17-12h25_31_thumb1.png?imgmax=800" width="644" height="330"></a></p><br /><p>When we clicked submit the button's onclick event was called where we call validate. In this case, because validation failed false was returned and the Ajax call back to the server was blocked by returning false.<br><br>When we enter 3 characters and click submit here's what we get:</p><br /><p><a href="http://lh6.ggpht.com/-zJXGa9Og9UY/TnTK7Uy0IEI/AAAAAAAAAlE/FAEoGyt1nis/s1600-h/2011-09-17-12h26_433.png"><img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2011-09-17 12h26_43" border="0" alt="2011-09-17 12h26_43" src="http://lh6.ggpht.com/-dDP22UD09I4/TnTK73CCi8I/AAAAAAAAAlI/oQf8FuRgl5c/2011-09-17-12h26_43_thumb1.png?imgmax=800" width="644" height="330"></a></p><br /><p>Since we entered 3 characters validation succeeded and returned true so the Ajax call back to the server wasn't blocked.. On the server we assigned the value of input's model to the message's model and then we cleared out the input's model to an empty string. Then we added the input and message components to the AjaxTarget which will cause them to render in the response by replacing their markup in the DOM.<br><br><strong>Summary<br><br></strong>As this article has shown, Wicket's enables you to to prepend its Ajax calls to the server with your own Javascript giving you great control over your Ajax processing. What might not have been so obvious is that Wicket doesn't just limit you to prepending and validation - you can also contribute Javascript that will be called in the success handler and the failure handler as well but those are subjects for a future article.</p> Jeff Schwartzhttp://www.blogger.com/profile/02747605277666816054noreply@blogger.com1tag:blogger.com,1999:blog-6189528330814114396.post-66159970052086406122011-07-19T00:00:00.000-04:002011-11-18T21:04:35.205-05:00Welcome to my blog dedicated to Wicket<b><span class="Apple-style-span" style="font-size: large;">Why The Wicket Evangelist?</span></b><br />
<b><br />
</b><br />
Have you ever experienced something so great that you just wanted to scream it out loud from the rooftop so everyone can hear you? Well that's sort of the role I've been taking on the last 2 years, preaching the benefits of using Wicket to any and all that are willing and smart enough to listen. A developer friend said I was like an evangelist and I liked that so much I've adopted it. Heck, if the shoe fits so to speak, right lol?<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">What to Expect </span></b><br />
<br />
Here I'll be only posting articles dedicated to Web development using Wicket. I'll still be posting to my other blog, Jeff's Blog, at http://jeff-schwartz.blogspot.com/ but it will be for more generalized & less specific subjects relating to software development.<br />
<br />
In the next few weeks I will begin posting articles here related to my last wicket related article at <a href="http://jeff-schwartz.blogspot.com/2011/05/apache-wicket-interfaces-to-master.html">http://jeff-schwartz.blogspot.com/2011/05/apache-wicket-interfaces-to-master.html</a>. Stay tuned because these articles will be very interesting.<br />
<br />
See you soon.<br />
<br />
JeffJeff Schwartzhttp://www.blogger.com/profile/02747605277666816054noreply@blogger.com0