Skip to main content

Using the YUI Calendar widget with JSF 2

Posted by driscoll on August 2, 2009 at 11:42 PM PDT

If you're not developing JSF with third party component libraries, you're really missing out on the best part of JSF. But there's lots of Ajax widgets out there, which contain all kinds of useful functionality. Wouldn't it be useful to use those within your JSF pages?


The Yahoo UI library is pretty nifty stuff, and the Calendar widget is useful, pretty, and powerful. Let's wire it into a JSF page, and bind the return of that widget to the property of a bean. How hard could it be? 71 lines, of which about 45 or so are non-boilerplate. Let's take a look. Here's what the page is going to look like when we're done:
Screen Shot


And, line by line, here's the breakout of the code - note that for this example, I've placed everything in one file, but you'd really want to break things out for a production environment.



   1    <?xml version="1.0" encoding="UTF-8"?>
   2    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   3    <html xmlns="http://www.w3.org/1999/xhtml"
   4          xmlns:h="http://java.sun.com/jsf/html"
   5          xmlns:f="http://java.sun.com/jsf/core"
   6          xmlns:ui="http://java.sun.com/jsf/facelets">
   7        <h:head>
   8            <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/yui/2.7.0/build/yuiloader/yuiloader.js"></script>
   9            <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
  10            <title>Test Binding</title>
  11        </h:head>
  12        <h:body>
  13            <h:outputScript name="jsf.js" library="javax.faces" target="head" />


The above code is mostly preamble, but there's one necessary part worth exploring - Line 8 - we must use the script tag, rather than a h:outputScript tag, since outputScript is only for local resources, and this is calling an external URL. We're using the Yahoo loader API, which we'll call later on line 53 to load everything we need from yahoo. We're loading this from Google's website, primarily to keep everything in one file - whether to use local files or Google's copies is an interesting question, but out of scope for this blog entry.


  14            <h:form id="form1" prependId="false">
  15                <div class="yui-skin-sam">
  16                    <div id="cal1Container"></div>
  17                </div>
  18                <h:inputHidden id="date" value="#{date.date}">
  19                    <f:convertDateTime pattern="MM/dd/yyyy"/>
  20                </h:inputHidden>
  21                <p>
  22                    The set date is:
  23                    <h:outputText id="out" value="#{date.date}" >
  24                        <f:convertDateTime/>
  25                    </h:outputText>
  26                </p>


Line 15-17 are the two divs that the YUI Calendar wants to see to set itself up. Note that we're calling calendar div "cal1Container". This will be the only part of our page that accepts input.


Line 18-20 is an h:inputHidden field that we'll use to store the date entered into by the Calendar widget. We call it "date", and we'll reference it later on in the page.


Line 21-26 is our output mechanism for this page - strictly speaking, we don't need this at all. After all, we're already displaying the value of the calendar widget in the widget itself. This is just a way to show that, yes, we are in fact updating the bean on the server.


  27                <script type="text/javascript">
  28                    var cal1;
  29                    var loader = new YAHOO.util.YUILoader({
  30                        base: "http://ajax.googleapis.com/ajax/libs/yui/2.7.0/build/",
  31                        require: ["calendar"],
  32                        loadOptional: false,
  33                        combine: false,
  34                        filter: "RAW",
  35                        allowRollup: false,
  36                        onSuccess: function() {
  37                            try {
  38                                cal1 = new YAHOO.widget.Calendar("cal1", "cal1Container");
  39                                cal1.render();
  40                                cal1.selectEvent.subscribe(handleSelect, cal1, true);
  41                            } catch (e) {
  42                                alert(e);
  43                            }
  44                        },
  45                        // should a failure occur, the onFailure function will be executed
  46                        onFailure: function(o) {
  47                            alert("error: " + YAHOO.lang.dump(o));
  48                        }
  49                    });
  50   
  51                    // Calculate the dependency and insert the required scripts and css resources
  52                    // into the document
  53                    loader.insert();


With the exception of lines 36-44, this code is pretty much just YUI Loader boilerplate code. In fact, much of it can even be generated automatically by utilities on the main YUI site. All that this code is doing, is simply loading all of the JavaScript and CSS files required to run the Calendar widget.


Lines 36-44 set up the calendar, display it, and then register a listener on the widget. Line 40 says that we should call the selectHandler function, whenever the cal1 component has a select event.


  55                    function handleSelect(type,args,obj) {
  56                        var dates = args[0];
  57                        var date = dates[0];
  58                        var year = date[0], month = date[1], day = date[2];
  59   
  60                        var txtDate = document.getElementById("date");
  61                        txtDate.value = month + "/" + day + "/" + year;
  62                        try {
  63                            jsf.ajax.request("date",null,{render: 'out', execute: 'date'})
  64                        } catch (e) {
  65                            alert(e);
  66                        }
  67                    }
  68                </script>
  69            </h:form>
  70        </h:body>
  71    </html>

And this selectHandler function is the last part of the page. We get the date selected in the widget, assign it to the date hidden field, and then commit it to the server via the jsf.ajax.request call. Note that we also use that ajax call to update the output field as well - though I mentioned earlier that that was not strictly required - you could just use the YUI Calendar widget with the hidden field, skipping any additional display of values.


There's more that can be done with this example - adding two way communication between the widget and the bean, for instance, or putting this into a component. But I've already spent a fair bit of text on this example, that's a topic for another day.


As always, let me know if you have any questions about this example in the comments below.

Related Topics >>

Comments

Java is very best and useful to upgrade many programs , شعر حزين

Java is very best and useful to upgrade many programs , شعر حزين

Thank you very much for posting this article. Its a very ...

Thank you very much for posting this article. Its a very useful article. We will be acquire lot of things from this site. pearson toronto limo

Calendar Recommendation

I am searching for a calendar that is placed in an iframe that queries a database to see what dates are selectable. Rolling over the selectable dates will dislay returned text. Lastly, when selecting a date, the database is queried again for a drop down to appear. The page can't refresh, so this calendar looks appealing. Do you recommend using this calendar, and do you have any pointers you could pass along on how to develop this? Lastly, if you recommend this calendar, can the specific references to the Yahoo javascripts be removed and installed locally? I would appreciate any advice you could offer, since I am on a short development timeline.

You don't need the extension - you want instead to do eval, see here: http://weblogs.java.net/blog/driscoll/archive/2009/07/including_scrip_1.... For a busy status indicator, you could instead use an event - see the ajax-queue demo in the project Mojarra codebase for one example.

Calendar Recommendation

I am searching for a calendar that is placed in an iframe that queries a database to see what dates are selectable. Rolling over the selectable dates will dislay returned text. Lastly, when selecting a date, the database is queried again for a drop down to appear. The page can't refresh, so this calendar looks appealing. Do you recommend using this calendar, and do you have any pointers you could pass along on how to develop this? Lastly, if you recommend this calendar, can the specific references to the Yahoo javascripts be removed and installed locally? I would appreciate any advice you could offer, since I am on a short development timeline.

Hi, I've been looking at "web-partialresponse_2_0.xsd" in the specs last night and see that there's an element called "partial-response-extensionType". Do you think this can be used to output something like JSON and stuff? To me, if you combine JSON output with [f:ajax render="@none"], it seems almost like you can achieve something similar to DWR or Seam remoting, except that there's no need for a third-party framework, as it's inherently supported by JSF standard. This will also open up a lot of possibilities to use JSF alongside with Javascript widget libraries like YUI, or ExtJS as well. Besides that, I have one question (or, rather, one request) about JSF 2 in general. I've been trying to find an example where, for some (not every) AJAX request, you do something like: 1. when request is initiated, pop up "in-progress" dialog 2. when response comes back, remove the dialog from view and do some effects on the updated elements to give visual cues to users (something like jQuery blinking, maybe). From my understanding, you can probably do 1. by using onClick attribute on JSF components, and for 2., you probably can output javascript as part of the partial response. But I recently found out from one blog that in JSF 2 there's something called "ClientBehavior": http://andyschwartz.wordpress.com/2009/07/31/whats-new-in-jsf-2/#behaviors So if you can show us how to achieve the effects with ClientBehavior that will be very helpful, as this seems like an elegant and highly reusable approach.