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

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.

Related

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

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.

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}">

p:selectOneMenu preselects previous item when noSelectionOption item is present

There is a problem with p:selectOneMenu selection when adding a f:selectItem.
View:
<p:selectOneMenu value="#{selectionTest.selectedName}">
<f:selectItem itemLabel="Select" noSelectionOption="true" />
<f:selectItems value="#{selectionTest.allNames}" var="varName" itemLabel="#{varName}" itemValue="#{varName}" />
</p:selectOneMenu>
Model:
private List<String> allNames;
private String selectedName;
public MenuSelectionTestBean(){
allNames = new ArrayList<String>();
allNames.add("Ahmed");
allNames.add("Mohamed");
allNames.add("Ibrahim");
allNames.add("Walid");
selectedName ="Walid";
}
Result:
The item "Walid" should be selected, however "Ibrahim" is selected instead. I think that PrimeFaces selects the item depending on its index in the list and not the value of the item.
How is this caused and how can I solve it?
I could reproduce your problem. I looked in the PrimeFaces source code. It's a bug in PrimeFaces SelectOneMenuRenderer which exposes only when an item with noSelectionOption="true" is been used. The renderer won't generate the HTML <option> element of the backing <select> element for that, but it will generate the <li> of the visual <ul> list for that. In other words, the <select> contains in your case 4 items and the <ul> 5 items. The <li> is selected by JavaScript based on the index of the <option selected>, exactly as you suspected. That explains your problem.
Your best bet is to report it as a bug to PrimeFaces guys. The renderer should also generate the <option> for that, or the JavaScript should select the option based on value instead of on index.
In the meanwhile, replacing the noSelectionOption="true" by itemValue="#{null}", or also itemValue="" when JSF is configured to interpret empty string submitted values as null, should solve your problem.

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>

PrimeFaces f:setPropertyAction with dataTable works only after a row is selected

Here is my Problem:
Backing bean is #SessionScoped
I have a p:dataTable with selectionMode set to single and selection #{bean.selectedCar}
first column in the table is a commandLink that updates a dialog :detailDialog, oncomplete shows the dialog and has an actionListener that hast to clear some property in the bean
f:setPropertyListener has a value #{item} and target #{bean.selectedCar}
I want that the user is able to click the link and the dialog will display the information for the object on the row, but it works only if a row in the dataTable was selected first. If no row was selected and the user clicks on the commandLink NULL is passed to the bean.selectedCar and the page hangs.
As a workaround I would like at least to be able to preselect the first row in the dataTable and hopefully this will do the trick.
You can re-use your f:setPropertyListener in your command link:
<p:commandLink value="show"
actionListener="#{bean.doSomething}"
oncomplete="dialog.show()">
<f:setPropertyListener value="#{item}" target="#{bean.selectedCar}"/>
</p:commandLink>
alternatively (since we are iterating through a dataTable) you can pass the current #{item} object to your <p:commandLink.../>:
<p:commandLink value="Show"
action="#{bean.selectThisCar(item)}"
oncomplete="dialog.show()"/>
Thanks #akoskm for your answer. The first variant was that what I used for the button. My problem was that (as the second option) this method conflicted with the selection option in the dataTable. Removing the selection="#{bean.selectedCar}" from the p:dateTable parameters was the salution of my problem. Thanks for the help.

Resources