2

I've got a list box and I want to catch change in selection in order to fill an other one according to it. I've tried in the following way:

<h:selectOneMenu id="comunitaValle" value="#{struttura.nomeComunitaDiValle}" 
     onchange="submit()" valueChangeListener="#{struttura.getComuniInComunita}">
<f:selectItems value="#{struttura.comunitaValleList}" />
</h:selectOneMenu>

It works fine, but the fact that in this page there are other parameters marked as

required="true"

and when the form is submitted I get my error messages controlling that those field has been set. How can I avoid to submit the entire form to avoid this to happen and still have the correct behaviour on the 2 list boxes?

EDIT:

I've reached a kind of solution (don't know if it is the best one) according to https://stackoverflow.com/a/4802483/2492962 :

<h:selectOneMenu id="comunitaValle" value="#{struttura.nomeComunitaDiValle}" 
      valueChangeListener="#{struttura.getComuniInComunita}" immediate="true">
<a4j:support event="onchange" reRender="cap"/>
<f:selectItems value="#{struttura.comunitaValleList}" />
</h:selectOneMenu>

Can it be fine? JBoss shows a warning message:

INFO  [lifecycle] WARNING: FacesMessage(s) have been enqueued, but may not have been displayed.

but the refresh seems fine.

Community
  • 1
  • 1
AnPe
  • 33
  • 7
  • Are you using JSF-2 or toolkit that provides AJAX-functionality? Since that sounds like the standard use-case for it. – mabi Nov 25 '13 at 08:57
  • Yes, but I wasn't able to do that with it. Any suggestion? – AnPe Nov 25 '13 at 08:59
  • Correction to above: OP isn't using JSF 2.x at all. – BalusC Nov 25 '13 at 14:53
  • Regarding your edit: are you trying to display FacesMessages in `getComuniInComunita`? – mabi Nov 25 '13 at 16:21
  • getComuniInComunita fill another drop down list according to the selected item in the first one. No FacesMessages are supposed to be shown here. I've got some FaceMessages in this page, indicating that some other fields hasn't been filled yet. Those are the "my error messages" I tried to explain in the first post and which I would not like to be shown after a selection of item in the drop down list. – AnPe Nov 26 '13 at 08:54

3 Answers3

1

I've reached a kind of solution (don't know if it is the best one) according to https://stackoverflow.com/a/4802483/2492962 :

<h:selectOneMenu id="comunitaValle" value="#{struttura.nomeComunitaDiValle}" 
      valueChangeListener="#{struttura.getComuniInComunita}" immediate="true">
<a4j:support event="onchange" reRender="cap"/>
<f:selectItems value="#{struttura.comunitaValleList}" />
</h:selectOneMenu>

<h:selectOneMenu id="cap" value="#{struttura.cap}"  >
<f:selectItems value="#{struttura.comuneIstatCapList}" />
</h:selectOneMenu>
Community
  • 1
  • 1
AnPe
  • 33
  • 7
  • Finally found the canonical article on it: http://balusc.blogspot.de/2007/10/populate-child-menus.html - I'd say go ahead with your solution but please read the article for potential pitfalls. – mabi Nov 26 '13 at 09:29
  • Great! FacesContext.getCurrentInstance().renderResponse(); is the answer I was looking for! Thank you! – AnPe Nov 26 '13 at 09:53
0

Say your JSF looks like this:

<h:selectOneMenu id="comunitaValle" value="#{struttura.nomeComunitaDiValle}">
   <f:ajax listener="#{struttura.getComuniInComunita}" 
           execute="@this" render="myListBox" />   
   <f:selectItems value="#{struttura.comunitaValleList}" />
</h:selectOneMenu>

<h:selectManyListbox id="myListBox" value="#{struttura.backingValueList}">
   <f:selectItems value="#{struttura.listBoxValues}" var="val" 
                  itemLabel="#{val.name}" />
</h:selectManyListbox>

Your backing bean then needs a method getComuniInComunita that accepts a javax.faces.event.AjaxBehaviorEvent parameter (see the reference for more information).

The execute attribute will cause JSF to only update/validate the select menu before invoking the listener method. Since your select menu only controls the list box(es), you can give a specific component id to update after the listener method finishes.

mabi
  • 5,279
  • 2
  • 43
  • 78
  • I'm getting java.lang.ClassNotFoundException: javax.faces.event.AjaxBehaviorEvent when calling public void getComuniInComunita(AjaxBehaviorEvent event) – AnPe Nov 25 '13 at 10:59
  • @user2492962 um, *are* you using JSF-2? If not, which toolkit do you use to get ajax support? – mabi Nov 25 '13 at 11:07
  • uhm.. maybe not.. I've just found this jsf-facelets-1.1.15.B1 – AnPe Nov 25 '13 at 12:27
  • FacesContext.class.getPackage().getImplementationVersion(); returns 1.2_12-b01-FCS, however it compiles correctly; the problem is runtime. – AnPe Nov 25 '13 at 12:40
  • @user2492962 you probably have a JSF2 API jar on your compile time classpath, but are not deploying it to your app server. – mabi Nov 25 '13 at 12:57
  • Ok! I've asked to my boss and understood that we cannot use jsf2 due to some problems. Is there a way to do want I've asked using jsf1.x? – AnPe Nov 25 '13 at 13:34
  • @andy JSF1 doesn't have built-in ajax functionality. You'd have to rely on your component library. Popular choices are Richfaces and PrimeFaces, do you run any of those? – mabi Nov 25 '13 at 13:39
  • Yes, I'm using Richfaces – AnPe Nov 25 '13 at 13:40
  • @AnPe I'll post another answer when I get back, have a look at the `` tag in the meantime. – mabi Nov 25 '13 at 13:42
  • `` is from RichFaces 4 which is designed specifically for JSF 2.x. For JSF 1.x, there's RichFaces 3 which has ``. – BalusC Nov 25 '13 at 14:54
  • @BalusC yeah, I've been using RF4 for too long. `` it is. – mabi Nov 25 '13 at 16:06
0

Here's a solution for JSF1.2, using Richfaces3.3 <a4j:support>:

<a4j:region>
  <h:selectOneMenu id="comunitaValle" value="#{struttura.nomeComunitaDiValle}">
     <a4j:support event="onchange" action="#{struttura.getComuniInComunita}" 
             ajaxSingle="true" reRender="myListBox" limitToList="true" />   
     <f:selectItems value="#{struttura.comunitaValleList}" />
  </h:selectOneMenu>

  <h:selectManyListbox id="myListBox" value="#{struttura.backingValueList}">
     <f:selectItems value="#{struttura.listBoxValues}" var="val" 
                    itemLabel="#{val.name}" />
  </h:selectManyListbox>
</a4j:region>

This is the closest I've come to replicating JSF-2. The <a4j:region> enables us to restrict processing to a subset of the page (works like the execute attribute in JSF-2).

In addition, you may find the Richfaces architecture overview to be helpful.

mabi
  • 5,279
  • 2
  • 43
  • 78
  • Cannot find limitRender attribute for . Moreover this solution gives me an exception: org.apache.jasper.el.JspMethodNotFoundException. Could it be a problem if getComuniInComunita return is void? – AnPe Nov 26 '13 at 09:03
  • Sorry about that, `limitRender` is called `limitToList` in RF3, I've changed that in the answer. I'm not sure about the method not found exception. I was using Jboss EL with RF3, which hacked around limitations in previous EL versions. So it may well be that you need to conform to the exact signature in the [docs](http://docs.jboss.org/richfaces/3.3.X/3.3.4.Final/en/tlddoc/a4j/support.html), which requires a `Object` return value. – mabi Nov 26 '13 at 09:08
  • Still seems not to find my method. If there aren't errors, my own solution seems to fit better. Anything wrong with it? – AnPe Nov 26 '13 at 09:17