Jim Driscoll's Blog

Notes on Technology and the Web

Using the YUI Calendar widget with JSF 2

leave a comment »

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                    });
  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];
  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.

(This article originally published on my java.net blog on August 9, 2009.)


Written by jamesgdriscoll

February 9, 2010 at 9:33 PM

Posted in ajax, JSF, YUI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: