Skip to main content

JSF 2.0: The f:ajax tag

Posted by driscoll on December 3, 2008 at 3:17 PM PST

In my previous post, I described a "switchlist" set of components and behavior. If you haven't already, please go ahead and read that post, to get the context for this one.


This time, we'll wire it up so that it uses Ajax to communicate back to the server. It's going to be a short post - because we're going to use a new feature of JSF 2.0 - the f:ajax tag. Here it is in action:



<h:selectManyListbox id="list1" value="#{listholder.list1}" styleClass="switchlist">
                <f:selectItems value="#{listholder.items1}"/>
            </h:selectManyListbox>
            <h:panelGroup id="buttonGroup" styleClass="switchlistButtons">
            <h:commandButton id="button1" value="&gt;&gt;"
                             actionListener="#{listholder.move1to2}" styleClass="switchlistButton">
                <f:ajax execute="form1:button1 form1:list1" render="form1:list1 form1:list2"/>
                </h:commandButton>
            <h:commandButton id="button2" value="&lt;&lt;"
                             actionListener="#{listholder.move2to1}" styleClass="switchlistButton">
                <f:ajax execute="form1:button2 form1:list2" render="form1:list1 form1:list2"/>
                </h:commandButton>
            </h:panelGroup>
            <h:selectManyListbox id="list2" value="#{listholder.list2}" styleClass="switchlist">
                <f:selectItems value="#{listholder.items2}"/>
            </h:selectManyListbox>

So, what do we have here? I've placed an ajax tag inside each commandButton. This tells JSF that when we render the page, we want to put an ajax request on the onclick event of the rendered button.


I could have also placed it inside the selectManyListbox, in which case it would have put the request on the onchange event of the rendered input tag. I didn't, because that isn't how I'd like the page to behave. You can also place the tag in the form itself, in which case all the different components get ajax requests associated with them (which can be a nifty shorthand).


The thing to remember is that action components (i.e., commandButton) get "onclick" events, and value holding components (like selectManyListbox) get "onchange" events.


You can also see that the ajax tag, like the JavaScript ajax request function, takes parameters like execute and render. These behave the same way here as they do in the JavaScript. Press one button, and we execute both that button (which fires the action listener) and it's associated listbox (so that set gets called on the values), and then render both listboxes, so we show our results. We could have instead chosen to just render the entire form, of course - but the whole point of doing this is to get ready to put this into a component.


But that's the next post. As always, feel free to ask questions below, and I'll do my best to answer them. This isn't the last we've seen of this tag, but that's enough for an introduction.


UPDATE: This feature isn't available in build 6 of the JSF 2.0 bundle. I'll try to get a build 7 out that includes this feature ASAP. On the plus side, you're really getting cutting edge information :-)


Update 2: The new release of build 7 is available on GlassFish v3 Prelude.

Related Topics >>

Comments

leewas: The best place to take questions and discussions that aren't around my post are the usual places to discuss JSF things. I'll do a blog on this shortly, but they are: The ##jsf irc channel on freenode.net. The webtier@glassfish.dev.java.net mailing list.

i think the java script ID approach is good enough, its easy to understand, i.e. form1:button1. Its easy enough and make sense.

Sorry for mistaken post. ------------------------------- For example: <h:form id="form1"> <ui:include src="fragment1.xhtml"/> <ui:include src="#{fragment}"/> </h:form> <h:form id="form2"> <ui:include src="fragment1.xhtml"/> <ui:include src="#{fragment}"/> </h:form>

What about using include? If one page fragment being included in another pages, the client id can't be determined in the design-time, and can be generated dynamically. For example: Then, in this situations, we should not use nesting or other NamingContainer around included page?

The faces UIComponent.findComponent rules make sense for people who know those rules. The make no sense to a JavaScript programmer, sadly. Also, the component separator is settable in JSF 2.0. Add it all up, and it makes for a very awkward set of rules. The EG felt that just using the in-page rendered id was simplest for users to remember and use - since you're going to need to use that anyway in the rest of the JavaScript code you write. This was discussed, however, and if others feel the same way you do (and tell us about it) there's still time to change it. Myself, I prefer the rendered id - but then, I'm more comfortable in JavaScript than JSF.

This is the best thing JSF JSR team did, harvesting the existing assets like RF, Facelets and Ajax work. Skinning standardization is also what we should keep on priority and again harvest, trinidad and RF and Icefaces and woodstock never work together from skin perspective, is this not critical enough. URL Bookmarking, are we harvesting SEAM?

Why don't follow the UIComponent#findComponent() 's rules? In findCompoent(), if i want to find the component in other form(or other NamingContainer), prepend the ':' to the path of id, like ':form2:button'. If i want to find the component in the same form, just use the id of component. I think the rules for referencing the component shoud be in accodance.

An important reminder: There is really nothing in the JSF 2.0 specification that has not been invented before - all about "harvesting".. Case in point - Facelets was developed by a community member, and that is the base for the JSF 2.0 Page Definition Language. With that in mind, and with respect to Ajax, we deliberately "recruited" key members from the Ajax community - members from RichFaces, ICEfaces, ADF Faces/Trinidad... to incorporate their existing ideas into the Ajax portion of the specification. There are also some very cool features w/r/t Ajax client/server side processing that should help with Ajax component library compatibity - stay tuned. -roger (JSF co-spec lead)

I'm currently blogging about Ajax, because we're ready to blog about it. It's still changing, but the basics work, and haven't changed in a big way in about a month, though they change in small ways daily (usually from my putbacks). State managment isn't an area that's done enough for blogging yet, sorry. As I've said before - if this looks like RichFaces to you (or ICEFaces, or DyanFaces, or Trinidad), that's because the folks who worked on JSF 2.0 come from all those projects. Ajax "zones" isn't in this release (at least, not in the DynaFaces sense), but you can get much the same functionality from doing a tag cascade, which I'll cover in a later blog. You can also say render: "form" to render the entire form, and execute on a span to execute all underlying components. JSF 2.0 includes facelets, and gets it's template handling from there. There's other discussions happening around that, but I'm not following them closely, since our deadline is approaching very, very rapidly.

i agree with you Rich Faces is a very mature product in combination with Ajax4jsf, but URL Bookmarking and skinning standardizing have been long standing pending issues for which people have raised issues on JSF, although most of them are addressed with SEAM2.x. But I will like to see them in standard spec so that small things dont spoil the JSF 2 goodness. State Management is also one such area, any update will help us a lot?

I am glad to see that's JSF took Richfaces way to implement Ajax support. For those who need functionality, described here can use a4j:support tag: http://www.jboss.org/file-access/default/members/jbossrichfaces/freezone... rahul_maha asked many right questions about Ajax usage optimization, State management API, page region, skinnability... Fortunately it is already available in Richfaces for FREE and I don't see any reason to reinvent and recode already existing features. May be Mojarra Team can reach some agreement with Jboss about including Richfaces into JSF 2.0 (may be with some tag renaming and some modifications...). Richfaces is good solid product. Available right now. They working on it about 2 years and now it is very cool library. Check out their demo: http://livedemo.exadel.com/richfaces-demo/richfaces/support.jsf?c=support this is amaizing!

I think ID generation logic is fine, till the time logic is clear and specified properly. Rich Faces also does the same. Also JSF 2 Public released!!, Great work Its good to see Ajax!! Its good to see PDL!! Its good to EzComp!! Its great to see many other things!! What about Bookmarkable URL? Skinning? also what I remember I read in one of Blog state management API is also getting revised, any updates? Also in ajax area, is it possible to submit a region of page? like in ajax4jsf? Please reply.

Why not server id's? Assuming you mean the one you specified in the JSF page, we'd have to disambiguate (remember, you can have two buttons named "button" in two different forms). Which means that if you have multiple forms, it'll get complicated quickly. What if you want to specify the "button" for form2, even though you have a "button" for form1? Out of curiousity, why would it be difficult for you to put in the form name if needed? What I mean is, is it hard to do for some reason I haven't thought of, or simply inconvenient? Guys, remember that the client id is just the server id plus the form id - and that the client id can equal the server id if you say prepend=false on your form tag. It's not too late for this to change, so feedback's important! Let us know.

We can't use server side ids? Why?

Client ids in f:ajax tag dude? Why not server side ids? _rogerio_

Thanks for trying it! You got that error because I'm a knucklehead - I forgot that this feature isn't in build 6! I'll get a build 7 out ASAP so you can start playing with the feature. I'm so sorry I wasted your time. I'll update the post as well.

I create a Web-project in NetBeans 6.5, downloaded latest mojarra binaries, added libraries to project but when i deploy it on Glasshfish v3 prelude i'v got this error: com.sun.faces.facelets.tag.TagException: /index.xhtml @52,99 Tag Library supports namespace: http://java.sun.com/jsf/core, but no tag was defined for name: ajax p.s. jsf2.0 for Glassfish V3Prelude was already installed too