How to hide components by selecting a new value on h:selectOneMenu? - jsf-2

I have a page with a h:selectOneMenu, and I want to hide a dataTable when I choose a new value on the h:selectOneMenu while some bean attribute values update. I'm trying diferent things, and I'm able to hide the dataTable by reloading the page. I have tried this using some JavaScript code, on onsomething attributes. In that case, those bean attribute values disapear although I use t:saveState (and I also need the view scope for the bean).
Here is a little example to clarify this:
<h:selectOneMenu id="list" value="#{Bean.id}">
<f:selectItems value="#{Bean.List}" var="element" itemLabel="#{element.name}" itemValue="#{element.id}"/>
<t:saveState value="#{Bean.id}"/>
<f:ajax listener="#{Bean.populateBean}" render=":form:period" event="change"/>
</h:selectOneMenu>
<h:selectOneMenu id="period" value="#{Bean.period}">
<f:selectItems value="#{Bean.listaPeriod}" var="period" itemLabel="#{period[1]}" itemValue="#{period[0]}"/>
<t:saveState value="#{Bean.period}"/>
</h:selectOneMenu>
<h:commandButton id="search" action="#{Bean.doSearch}"></h:commandButton>
<t:dataTable id="data" value="#{Bean.configList}" rendered="#{Bean.search}"
<t:column>
...
</t:dataTable>
And Bean.doSearch changes Bean.search to true. How can I hide the dataTable when I choose a new value on h:selectOneMenu id="list"?
EDIT:
In short, the search button renders the table, and I would want to hide that table when I just choose a new value on the "list" dropdown without reloading the page. Now, the <f:ajax> is used only to rerender the "period" dropdown value.
Thanks in advance!

Your question is hardly understandable, but if you want to kick the datatable out of your view on ajax request triggered by your dropdown, you need to enclose it in a component that's always present in the view so that HSF would know what to rerender when ajax call successfully finishes:
<h:panelGroup id="rerender">
<t:dataTable rendered="#{bean.condition}" ...>
....
</t:dataTable>
<h:panelGroup>
Of course, to get it working you should specify id of the component to be rerendered:
<h:selectOneMenu ...>
...
<f:ajax listener="#{bean.populate}" render="rerender" />
</h:selectOneMenu>
Note that if both dropdown and datatable components belong to the same form, it's not necessary to specify absolute id of the latter's parent. Also note that specifying event is redundant, as it already defaults to the right one. Finally, as you're on JSF 2.x, using save state is not necessary, just bind the values of your form data to a view scoped bean.
The last thing to note is the fact that you fail to conform to the Java Naming Conventions, the thing you should correct as soon as possible.

Related

Primefaces selectors not updating a panelGroup

I am trying Primefaces selectors and it appears that it couldn't update an panelGroup.
<h:panelGroup layout="block" styleClass="updateMe">
<h:outputText value="#{bean.value}"/>
</h:panelGroup>
<h:form>
<h:inputText value="#{bean.value}"/>
<h:commandButton value="submit">
<p:ajax process="#form" update="#(.updateMe)" oncomplete="alert(1)"/>
</h:commandButton>
</h:form>
In this case the panelGroup never gets updated. But if I change the panelGroup to <p:outputPanel>, then it worked fine.
Observing the generated HTML, the only difference is that the <span> generated by panelGroup doesn't have an id while the one generated by outputPanel has an id. Could this be the reason why the first one is not getting updated (cos jQuery selector couldn't find the component id?)
If that is the case, is there any other component that does not have any ids and should be avoided when using Primefaces selectors?
When using Primefaces selector jQuery is used to select components on client side, and discover their client ids. When AJAX is sent one of parameters that is sent is javax.faces.partial.render whose value are client ids of components which should be updated. If component doesn't have client id it can't be updated directly, you can update parent component for example. Provide id attribute for panelGroup and try to update it with Primefaces selector.

Update sibling component in JSF 2 / Primefaces

I have the following component tree on my page
form
tabView
datatable
dialog
Now I want to update the dialog component when a row is selected in the datatable.
I tried something like:
<p:ajax event="rowSelect" update="#parent:detailsView" oncomplete="detailsViewDialog.show()" />
where detailsView is the id of a panelGroup within the p:dialog.
Only having update="#parent" works but is it not a solution to always reload the whole table only to display the dialog.
Can anybody give me a hint?
Regards,
Florian
The data table is by itself a NamingContainer component, so it's hard to use a relative client ID. You'd basically need to specify the absolute client ID:
<p:ajax ... update=":formId:tabViewId:detailsView" />
Alternatively, you could also bind the UIComponent with ID detailsView to the view by binding attribute and use UIComponent#getClientId() in the update attribute:
<p:ajax ... update=":#{detailsView.clientId}" />
...
<h:panelGroup id="detailsView" binding="#{detailsView}">

How to make p:selectOneMenu show current value?

I have a <p:selectOneMenu> to choose the category for an item from. By default the menu displays the first entry of someBean.selectedParty.categories as selected. But the item already has a current category at someBean.selectedItem.category that I want to be displayed/selected. How can I achieve that?
<p:selectOneMenu value="#{someBean.selectedItem.category}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{someBean.selectedParty.categories}" var="category" itemLabel="#{category.name}"/>
</p:selectOneMenu>
As long as the getter for someBean.selectedItem.category returns a value available in the list , it will show the value as selected.
However there are some gotchas:
1) The default value probably should be set in the bean constructor
2) The bean (someBean) cannot have the RequestScope - As every single HTTP request, including Ajax requests, would create a completely brand new instance of the bean with all properties set to default. If your bean is RequestScope, change to ViewScope
3) As you are "cascading" from someBean to selectedItem to category, note that the selectedItem and selectedParty must be the same through (not only same content but also same memory adress) or the lifecycle of JSF will stop. I guess you are setting the selected objects earlier. If you are using AJAX, try to post a "full" request to a new page with the drop-down to debug this.
4) To simplify this, you could try to move the category and categories directly into someBean so the page should look like
<p:selectOneMenu value="#{someBean.category}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{someBean.categories}" var="category" itemLabel="#category.name}"/>
</p:selectOneMenu>

h:selectOneMenu default item to null, clear empty item value, required field

Hello I'm having trouble with the following piece of code:
<h:selectOneMenu id="selectTipoAutorizacion"
value="#{autorizacion.codigoTipoAutorizacion}"
required="true">
<f:selectItems
value="#{cc.attrs.controller.getListaTiposAutorizacion(autorizacion)}"
var="tipoAutorizacion"
itemLabel="#{tipoAutorizacion.nombreTipoAutorizacion}"
itemValue="#{tipoAutorizacion.id.codigoTipoAutorizacion}" />
<a4j:ajax event="change" execute="#this"
listener = #{myListener.listener} render="selectAutorizador" />
</h:selectOneMenu>
The problem is that the default selected value is always the first one of the tag. And that's bothering the users, cause some data is loaded based on the selected item value..., however that info it's not loaded until the change event occurs (a4j:ajax tag), so right now the user has to select another item, and then select the previous one in order to see the default's item related info.
I addressed the problem by loading the default's item related info at the beginning, however the user doesn't like this. Because it could lead to confusion. So the question is... how could I avoid that behaviour? What I want is the selectOneMenu to load with a clear value( Like if there weren't any f:selectItems). Thanks a lot.
Your field is required, there should be nothing valid to default to in this case. Add an empty selectItem to the top of the list: selectItems.add(0, new SelectItem("", "")); or this way: <f:selectItem itemValue="" itemLabel="" />
By default it would then select the empty selectItem.
The user will be forced to make a choice as the required="true" does not allow an empty selection.
Just preload the desired data in the (post)constructor of the bean.
if (codigoTipoAutorizacion != null) {
// Preload all other desired data as well.
}
Add an f:selectItem before the f:selectItems, with an empty value, or something like "please select ...", and mark it as non-selectable.

Understanding navigation in JSF

Trying to build a simple JSF application. One i don't get is, what mechanism is to use to trigger page reload. I have tried following
<h:selectOneMenu
id="ChallengesListBox"
onchange="submit()"
valueChangeListener="#{bean.projectselected}">
<f:selectItems value="#{bean.projectnames}"/>
</h:selectOneMenu>
<h:commandButton value="submit" action="#{bean.submit}" />
with
public String submit() {
this.description.setRendered(true);
return null;
}
But this has no effect. The bean method
public String submit()
remains untouched, as I can see in debug mode.
This is not related to navigation. There are many causes why a bean action method is not invoked. You can find them all in this answer: commandButton/commandLink/ajax action/listener method not invoked or input value not updated
I suspest that you've either simply no <h:form>, or that you have multiple buttons in the form (the first one would then be invoked on submit()), or that the button is by itself not rendered during processing of the form submit.
Unrelated to the concrete problem, this JSF 1.x style approach is very clumsy. As you're apparently already on JSF 2.x, I suggest the following much simpler approach:
<h:selectOneMenu value="#{bean.projectname}">
<f:selectItems value="#{bean.projectnames}" />
<f:ajax render="somepanel" />
</h:selectOneMenu>
<h:panelGroup id="somepanel">
<h:outputText value="#{bean.description}" rendered="#{not empty bean.projectname}" />
</h:panelGroup>
(this will render the #{bean.description} value whenever the #{bean.projectname} is not null/empty according to the selection of the drop down list)
And make sure that you remove all binding attributes to the backing bean. Also make sure that the bean is #ViewScoped whenever you have input/button components inside the <h:panelGroup id="somepanel">.

Resources