Form Completion One of the prototypical Ajax use cases is form completion, in which a user enters information in a field that causes other fields on the page to change. For example, we can use Ajax to react to the value entered into a zip code field, as shown in Figure 11-2. When the user leaves the zip code text field, we send an Ajax request to the server, passing the current value of the zip code field as a request parameter. We associate the zip code field with the event handler, like this: <h:inputText size="5" value="#{bb.zip}" onblur="zipChanged(this.value);"/> The zipChanged function uses Prototype to send the Ajax request: <script type="text/javascript" language="Javascript1.1"> <!-- function zipChanged(zip) { if(zip.length != 5) { clearCityAndStateFields(); } else { new Ajax.Request( "zipChanged.ajax", // URL { method: "get", // HTTP method parameters: "zip=" + zip, // Request params onComplete: processZipCodeSelection, // callback }); } ... When the request is finished, Prototype calls the onComplete callback specified above. Here's what that function looks like: ... function processZipCodeSelection(req) { var cityAndState = req.responseText.split(','); setCityAndStateFields(cityAndState[0], cityAndState[1]); Fat.fade_element("form:city"); Fat.fade_element("form:state"); } function clearCityAndStateFields() { $("form:city").value = ""; $("form:state").value = ""; } function setCityAndStateFields(city, state) { $("form:city").value = city; $("form:state").value = state; } --> </script> Once again, we are using Prototype in this example. Prototype greatly simplifies our JavaScript, mainly through the use of Prototype's Ajax.Request object, which executes the Ajax request, and the $() function, which is a handy shortcut for window.document.getElementById(). In the preceding code fragment, we are also using the Fade Anything Technique's Fat JavaScript object to fade both the city and state fields after we update them. The URL that we used for the Ajax call zipChanged.ajax is handled on the server by a servlet: public class AjaxServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); response.setHeader("Cache-Control", "no-cache"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().write(getResponseForZip(request.getParameter("zip"))); } private String getResponseForZip(String zip) { return "97402".equals(zip) ? "Eugene,Oregon" : "NO DATA,NO DATA"; } } If the servlet finds the zip code in our database, it writes a simple string to the response with this format: City,State. If we do not find a match, we return this instead: NO DATA,NO DATA. When the request is finished, we parse that response string and set the inner HTML of the city and state text fields to their respective values. Of course, in a real application, you might opt for a more robust database of zip codes. Note | The preceding form completion example requires very little knowledge of JSF, other than attaching JavaScript event handlers to JSF components (with DHTML attributes provided by the tags in the HTML tag library) and knowing how JSF creates client identifiers from component IDs. As that example illustrates, simple Ajax interactions can be easily implemented in a JSF application without much knowledge of JSF itself. | |