Skycelot
Skycelot

Reputation: 33

How to hide a JSF component on a Validate phase

I have 3 listboxes: the first with types, the second with subtypes of the chosen type and the third with elements of the chosen type and subtype.

<p:selectonelistbox id = "types" rendered = "true" valuechangelistener = "#{bean.selectType}" onchange = "submit()" />
<p:selectonelistbox id = "subtypes" rendered = "#{bean.subtypesFlag}" valuechangelistener = "#{bean.selectSubType}" onchange = "submit()" />
<p:selectonelistbox id = "elements" rendered = "#{bean.elementsFlag}" />


@viewscoped
...
private Boolean subtypesFlag = false;
private Boolean elementsFlag = false;
public void selectType(ValueChangeEvent  event) {
  subtypesFlag = true;
  elementsFlag = false;
}
public void selectSubType(ValueChangeEvent  event) {
  elementsFlag = true;
}

The first listbox is always displayed, the second only when some type is selected, the third only when subtype is selected.

When I open the view only types are rendered. Then I press some type, subtypes become visible. Next I press some subtype, elements become visible. Everything is working fine.

But when I select another type, I want to show only subtypes, but no elements listbox. And there I have a problem. When I really select another type, I get all three listboxes visible. When I press again another type once more I see only types and subtypes, no elements listbox.

That seems to be an interesting fact, when on apply request values phase your component has rendered flag set to false and it becomes true during validate phase (when value action listeners are invoked) it changes its rendered state and IS rendered on render response phase. But when its rendered flag is true on apply request values phase and gets to false on validate phase it doesn't see the change and is STILL rendered on render response phase.

Can I change its state to false somehow (programmatically maybe or invalidate its rendered flag) on validate phase?

Mojarra 2.2.4, Primefaces 4, Glassfish 4.

Upvotes: 3

Views: 1061

Answers (1)

BalusC
BalusC

Reputation: 1108632

valueChangeListener is the wrong tool for the concrete functional requirement of executing a method during the invoke application phase (as you clearly intented). It's indeed executed during the validations phase (as you discovered). You need <f:ajax listener> instead. Perhaps you were focusing too much on JSF 1.x flavored examples while you're actually using JSF 2.x.

Fix it accordingly:

<p:selectOneListbox id="types">
    <p:ajax listener="#{bean.selectType}" update="@form" />
</p:selectOneListbox>
<p:selectOneListbox id="subtypes" rendered="#{bean.subtypesFlag}">
    <p:ajax listener="#{bean.selectSubType}" update="@form" />
</p:selectOneListbox>
<p:selectOneListbox id="elements" rendered="#{bean.elementsFlag}" />

Don't forget to remove the ValueChangeEvent argument from the methods.

See also:

Upvotes: 5

Related Questions