Appliweb

All dimensions of your web developments

Affichage des articles marqués jsf

More dynamic form with ValueListener

Next difficulty: I add a checkbox, and when the user check this box, I want some other fields to appear.

For now, only one input field will be enough, but this field, when displayed, must be filled by the user. It is mandatory.

How do you do that ?

Simply add the checkbox and the input, and map the rendered attribute of the input to the same model value of the checkbox.

1
2
3
4
5
6
7
8
9
10
11
<ice:outputLabel value="Extended Search:" />
<ice:selectBooleanCheckbox id="extendedSearch"
   value="#{searchPage.extendedSearch}" />
<ice:outputLabel value="Extension:"
   rendered="#{searchPage.extendedSearch}"/>
<s:decorate template="/layout/decorate.xhtml" rendered="#{searchPage.extendedSearch}">
    <ice:inputText id="extension"
       value="#{searchPage.extension}" required="true"/>
    <ice:message for="extension" styleClass="message"
       errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"/>
</s:decorate>

The result should be, after a click in the check box:

But, nothing happens.

We have to tell JSF to generate an event as soon as the user click on the checkbox. By default, JSF does nothing.

We simply use our famous attribute partialSubmit= »true »

1
2
3
<ice:selectBooleanCheckbox id="extendedSearch"
   value="#{searchPage.extendedSearch}"
   partialSubmit="true" />

Now, when we click on the checkbox, we have the dependant input field displayed or not. Great ! But we’re not done yet with this.

Let’s try to input an incorrect value in the integer field, then check the box:

Ooopps, the integer input just gets validated before the checkbox can modify the model value, so the dependant input field don’t display.

We need to set the immediate= »true » attribute:

1
2
3
<ice:selectBooleanCheckbox id="extendedSearch"
   value="#{searchPage.extendedSearch}"
   immediate="true" partialSubmit="true" />

We must leave the partialSubmit= »true », otherwise no event occurs when clicking on the checkbox.

After testing, same (bad) result ! The validation error is displayed, but what’s annoying is that the checkbox is now checked, without the dependent input field displayed !

We need another trick: This trick, is to call a method when the value of the checkbox is changed. We do it like that:

1
2
3
4
<ice:selectBooleanCheckbox id="extendedSearch"
   value="#{searchPage.extendedSearch}"
   immediate="true" partialSubmit="true"
   valueChangeListener="#{searchPage.extendedSearchChanged}" />

And the code for the called method is this:

1
2
3
4
5
6
7
8
9
public void extendedSearchChanged (ValueChangeEvent evt)     {
// We set the value so that the
//  depedant fields are displayed or not
setExtendedSearch((Boolean)evt.getNewValue());

// Using this, we bypass all validations
// stuff, and redisplay directly the page.
FacesContext.getCurrentInstance().renderResponse();
}

And the result is just perfect! You can check / uncheck, you see the dependant input field disappearing or appearing accordingly, even if bad values are entered.

Icefaces partialSubmit and immediate compared

Now let’s try something else: We want, next to the « Search » button, another one, « Back to Home », that goes directly to another page, let’s say the home page.
If we simply add the button in the .xhtml page, and click on it, we have the following result:

1
2
3
<ice:commandButton id="homeAction"
value="Back to Home"
action="#{searchPage.backToHome}" />

Result:

You can see that we cannot go back to the homepage without setting required fields in the form. That’s clearly not good.
One of the solution to this, according to icefaces documentation, is to use partialSubmit= »true » in the button. This tell Icefaces to ignore all mandatory components that are not filled.
Let’s try:

1
2
3
<ice:commandButton id="homeAction"
value="Back to Home" action="#{searchPage.backToHome}"
partialSubmit="true" />

And the result is working !

But, suppose that you’ve typed a wrong value in the first field, and press « Back to home » ?
Here is the result:

What happened ? partialSubmit bypassed the required check, but not the integer validation.

To avoid these 2 checks, we need to use another attribute in the button, it’s immediate= »true ». That means: When I press the button, just handle the button’s action, and forget about all other fields.

1
2
3
<ice:commandButton id="homeAction"
value="Back to Home" action="#{searchPage.backToHome}"
immediate="true" />

And the result works, even with a bad value in the integer field!

Basic error handling

Seam, JSF and Java all team up together to help developers in displaying error messages to the user.

JSF provides the basis, with the FacesMessage mechanism. Anywhere in your code, you can create FacesMessages, and add them to a FacesMessages object. Then, when the next page displays, the error messages are displayed to the user.

You can use special tags for that in your .xhtml page:

1
2
<ice:messages id="messages" globalOnly="true" styleClass="message"
    errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"/>

Notice icefaces allows us to set various css style depending on the type of error.

The result is here:

Now, when a validation is bad, we want to highlight the input field, then display the error message next to it. Fortunately, JSF allows a developer to assign an error message to a field, and by default the validators and converters do just that.

And Seam, allows us to define specific html code when a field is in error. This is done using the s:decorate tag, and the best option is to refer to a template file that will be reused for all fields.

Now the input field is declared like that:

1
2
3
4
5
<s:decorate template="/layout/decorate.xhtml">
  <ice:inputText id="nbElements" value="#{searchPage.nbElements}" />
  <ice:message for="nbElements" styleClass="message"
    errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"/&gt;
</s:decorate>

and for the field that must not be null or empty, we just add an required= »true » attribute:

1
2
3
4
5
<s:decorate template="/layout/decorate.xhtml">
  <ice:inputText id="notNull" value="#{searchPage.notNull}" required="true" />
  <ice:message for="notNull" styleClass="message"
      errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg"/>
</s:decorate>

and the content of the error template file is this:

1
2
3
4
5
6
7
<div class="errorDiv">
  <span class="#{invalid?'errors':''}>
    <s:validateAll>
      <ui:insert/>
    </s:validateAll>
  </span>
</div>

The errors css style just sets the component border to Red.

Now, if we try some basic errrors, like by inputing letters in a field mapped to an integer value, here is the result:

Notice the error message is more precise than the previous screenshot. Any error message can be changed in JSF by a simple properties file.

That’s all for basic error handling. Next time, we’ll try to see the behavior of the current page for all errors defined in the first part.

Using Seam, JSF and IceFaces, I’m trying to write THE form.

I mean, even the basic stuff like a good form is not easy to do, and we’re experiencing some troubles in our project.

So I decided to try to write the « perfect » and « working in all cases » form.

What features are needed ?

  1. Input must be validated. A integer field should not accept letters for example.
  2. Fields can be mandatory or not
  3. Erroneous fields should be highlighted, with an error message.
  4. I want to select easily a date. Moreover, I want to select it, even if a mandatory field has not been set.
  5. A Field can update values and rendering of other fields. Even if some fields contains errors

Well, that’s all for now. I can’t think of others features, but I’m quite sure I forgot some. We’ll add it later.

The basic:

For beginning, I’m just going to write an input field accepting integers, a date selector, and another field that is mandatory.

To do this, a few xhtml lines of code are needed:

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
<ice:form id="searchForm" >
  <ice:panelGrid id="homePanelGrid" columns="2" columnClasses="rightMenu,leftMenu">
    <ice:outputLabel value="Nb Elements:" />
    <ice:inputText id="nbElements" value="#{searchPage.nbElements}" />
    <ice:outputLabel value="Not null:" />
    <ice:inputText id="notNull" value="#{searchPage.notNull}" />
    <ice:outputLabel value="Start Date:" />
    <ice:selectInputDate id="startDate" value="#{searchPage.startDate}" renderAsPopup="true" />
  </ice:panelGrid>
  <ice:commandButton id="searchAction" value="Search" action="#{searchPage.search}" />
</ice:form>

Quite easy, and the result is here:

Now, if I try to enter an invalid value in the integer field and press the button:

No error message is displayed…

We’ll see in our next chapter how to handle error messages.

A Web Designer

My business is to develop web applications in Java.

I would like to talk about a simple business application I do, where users insert / review data from a database.
We choose the standards librairies: JSF-Seam-Hibernate with RichFaces as the U.I. components.
This time, we were lucky enough to hire a web designer ! Big Time !

Let me share with you some of the things I’ve learned working with him.

Organization

First, how the development was organized ?

1. The web designer write the screens in jpg using Photoshop and  Illustrator

2. After several round-trip with the client, the « final » version eventually emerges

3. The web designer then writes the pages in HTML / CSS with the same look and feel

4. I develop a basic JSF page with the Seam backing beans. It only displays the needed information

5. We incorporate its HTML / CSS  into my JSF pages.

The last step is the  tricky one, so let me update with the problems we encountered….

HTML to JSF

CSS problems

The web designer of course came with it’s own set of css styles, with it’s own way of creating the page structure and graphics.
However, the RichFaces JSF library comes with it’s own set of css styles and page structure.

For example, the datatable component generates an HTML <table>, whereas the web designer was expecting <div>. We overcome this problem by changing its HTML with <table>. It’s quite understandable to use a <table> for displaying tabular data in HTML. It’s only by using <table> to position precisely elements that you make a mistake.

Aligning text with images.

Next problem : « align » attribute is not generated by the JSF graphicImage component.
Of course, our web design uses this attribute to align text with image…. Once again, the web designer changed it’s page design to support this. It is now better to use CSS to do this anyway.

A damned simple button

This one is really scary. The web designer don’t use <input type= »submit » /> in it’s forms, but <button>.
Never seen this tag anywhere, but it’s a standard one.

The web designer used it to enable the rollover effect, and to insert <span>…</span> around the text to apply images in the button via css. It’s button was: <button type= »submit »><span><span><span>Submit</span></span></span></button>
I haven’t seen any JSF library with a command button generating HTML.

Of course, you can tell me to create one new JSF Component, but common, I’ve already created some, and it’s way too complex for a simple button ! I have to rewrite the HTML renderer, manage all the subtle things in the implementation…
Currently, our solution is to created a javascript code (called using click event) to submit the form. Not very nice.

Conclusion

We’ve done only the first page of our application, and I’m really wondering if we took the right library. I believe now that in case you have a web designer in your team, you shouldn’t use libraries that generate HTML for you, like JSF or gwt, but instead use a framework allowing to generate the precise HTML the designer wants (maybe Tapestry, or plain JSP ?)