Best way to add a "nothing selected" option to a selectOneMenu in JSF - jsf

I was wondering what would be the best or easiest way to allow a user to select nothing in a selectOneMenu.
My example: I have a list of registered users and the administrator should be able to filter the list of displayed users by some criterias. These criterias, like the usertype (employee, customer, ...) can be chosen by selectOneMenus, like this:
<h:selectOneMenu value="#{myBean.selectedUsertype}" converter="#{usertypeConverter}">
<f:selectItems value={myBean.usertypes}" />
</h:selectOneMenu>
When the corresponding selectOneMenu is being backed by a list of POJOs using a converter, how can I add an item to the list indicating that the user didn't choose any specific item? Currently I have a dummy usertype object displaying the label "---", but this is causing several problems in other areas of my application and I don't think that this is the best solution.

Just explicitly set the select item value to null.
<h:selectOneMenu value="#{bean.selectedItem}">
<f:selectItem itemValue="#{null}" itemLabel="--select--" />
<f:selectItems value="#{bean.availableItems}" />
</h:selectOneMenu>
No, an empty string like itemValue="" is not sufficient. It really has to be null. Otherwise you run into trouble as described in this Q&A: Using a "Please select" f:selectItem with null/empty value inside a p:selectOneMenu.
If the item happen to be required="true" and you're using JSF 2.x, then you could add noSelectionOption="true" to the select item. This is only useful if you also set hideNoSelectionOption="true" on the selection component. It will then hide the empty option in the list once the enduser selects a different item, hereby making it impossible to re-select the empty option.
<h:selectOneMenu value="#{bean.selectedItem}" hideNoSelectionOption="true">
<f:selectItem itemValue="#{null}" itemLabel="--select--" noSelectionOption="true" />
<f:selectItems value="#{bean.availableItems}" />
</h:selectOneMenu>
See also page 114 of The Definitive Guide to JSF under section "SelectItem tags":
Note that a select item with value of #{null} can be used to present the default selection in case the bean property associated with selection component's value attribute is null. If you have consulted the tag documentation of <f:selectItem>, then you'll perhaps have noticed the noSelectionOption attribute and have thought that it was intended to represent a "no selection option". Actually, this isn't true. Many starters indeed think so, as you can see in many forums, Q&A sites, and poor-quality tutorials on the Internet. In spite of the misleading attribute name, it does not represent a "no selection option".
A better attribute name would have been hideWhenOtherOptionIsSelected, and even then it works only when the parent selection component has explicitly a hideNoSelectionOption="true" attribute set. So, hideWhenOtherOptionIsSelectedAndHideNoSelectionOptionIsTrue would ultimately have been the most self-explanatory attribute name. Unfortunately, this wasn't very well thought out when the noSelectionOption was implemented in JSF 1.2. Requiring two attributes for this attribute to function shouldn't have been necessary. The primary purpose of this attribute pair is to prevent the web site user from being able to re-select the "no selection option" when the component has already a non-null value selected. For example, by having it prepared in a #PostConstruct method, or by re-rendering the component after a form submit with a non-null value.
Copyright disclaimer: book is written by me.

Add a single selectItem with null value;
<h:selectOneMenu value="#{bean.question}" required="true" requiredMessage="Please select a question">
<f:selectItem itemValue="#{null}" itemLabel="Select" />
<f:selectItems value="#{bean.questions}" />
</h:selectOneMenu>

We can in primefaces (when we have to use <p:selectOneMenu... from some reason like using <p:ajax..) add the following empty item:
<f:selectItem itemValue="#{null}" itemLabel="--select--" itemDisabled="#{Mybean.value ne null}" />
Note: In such case we don't need the following two tags:
hideNoSelectionOption="true"
and
noSelectionOption="true"

Related

<h:selectOneMenu with conditional <f:selectItems shows options twice

I want to use a selectOneMenu to have a user choose a value. In some cases I want to disable one of the values shown in the menu. I tried using render on both the selectItems as well as selectOneMenu as well as added a ui:fragment around the Menu but I always get all the values from both lists shown. Any ideas how to prevent that?
Here my current last try that again resulted in twice the list and the item in question once enabled and once disabled in it:
<ui:fragment rendered="#{cc.attrs.showP==true}">
<h:selectOneMenu id="type" binding="#{cc.type}">
<f:selectItems value="#{typeDAO.findAll()}"/>
</h:selectOneMenu>
</ui:fragment>
<ui:fragment rendered="#{cc.attrs.showP==false}">
<h:selectOneMenu id="type" binding="#{cc.type}">
<f:selectItems value="#{typeDAO.findAll()}" var="item" itemDisabled="#{item=='P'}"/>
</h:selectOneMenu>
</ui:fragment>
Your concrete problem is caused because you're binding physically multiple components to the same variable.
<h:selectOneMenu ... binding="#{cc.type}" />
<h:selectOneMenu ... binding="#{cc.type}" />
If the getter behind binding returns non-null, then JSF will use it instead of creating a new one. Basically, the second tag will reuse the component created in the first tag and set/add all attributes/items to it.
Your particular case can be solved in at least two ways:
Use JSTL to build the JSF component tree conditionally instead of using JSF to render the HTML output conditionally. You shouldn't have physically multiple components in the JSF component tree sharing the same binding let alone the same id.
<c:if test="#{cc.attrs.showP}">
<h:selectOneMenu id="type" binding="#{cc.type}">
...
</h:selectOneMenu>
</c:if>
<c:if test="#{not cc.attrs.showP}">
<h:selectOneMenu id="type" binding="#{cc.type}">
...
</h:selectOneMenu>
</c:if>
Make your code DRY. I.e. get rid of all code duplication.
<h:selectOneMenu id="type" binding="#{cc.type}">
<f:selectItems value="#{typeDAO.findAll()}" var="item" itemDisabled="#{not cc.attrs.showP and item eq 'P'}" />
</h:selectOneMenu>
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?
JSTL in JSF2 Facelets... makes sense?
Guess I found it - bit weird to answer my question though. I think it's because the possible values of the menu are created before the rendered attributes are evaluated and since I did bind both menus to the same variable/id I got all items of the two menus. Thus I now used different names and then in my composite component have some logic that checks which one is used and continues to use the right value. Works :-)
Bit weird to me is this thing that as a developer u have to know when the attribute list is built in comparison to when the rendering happens. I recently had a similar issue with foreach and repeat. Is there any way to know these things as part of some overarching concept that I can remember or is that really case by case?
Thanks guys!

Adding dynamic drop down components in JSF

My requirement is like this. I have a selectMenu with some values (Examples: Engineering, Medicine, Law etc..,) . Suppose if I select Engineering in the drop down, I want another dropdown menu created dynamically which has values related to Engineering (Example: Electronics, Computers, Electricals etc..,). How do I achieve this in JSF 2.0 ?
You need to perform an ajax request when first h:selectOneMenu's selection change. This request will update the selectable items in the second h:selectOneMenu. After the ajax request, you must render the second h:selectOneMenu again, with the updated values.
Page:
<h:selectOneMenu value="#{bean.selectedSubject}">
<f:ajax listener="#{bean.changeSubject}" render="speciality_selection" />
<f:selectItems value="#{bean.subject}" />
</h:selectOneMenu>
<h:selectOneMenu id="speciality_selection" value="#{bean.selectedSpeciality}">
<f:selectItems value="#{bean.subjectSpecialities}" />
</h:selectOneMenu>
Managed bean:
public void changeSubject(){
//Loads the specialities depending on the selected subject
subjectSpecialities = loadSpecialitiesForSubject(selectedSubject);
}

JSF select menu problem

I am developing a jsf,richfaces application.where i want to populate the values of second select menu on the basis of selecting the choice from the first one .How i can achieve this.
<h:outputText id="section1" value="Section" />
<h:selectOneMenu id="section2" value="#{content.sectionName}" >
<f:selectItems value="#{content.sections}" />
</h:selectOneMenu>
what exactly i want is:
I have two tables one for category and one for section.
If a user choose a category from drop down menu then the other drop down menu for section should have the values only for selected category.
Please he
As per your question history you're using Ajax4jsf/RichFaces. Better use <a4j:support> instead of valueChangeListener.
<h:selectOneMenu id="section2" value="#{content.sectionName}" >
<f:selectItems value="#{content.sections}" />
<a4j:support event="onchange" action="#{content.changeSection}" reRender="otherMenuId" />
</h:selectOneMenu>
In the changeSection() method you need to populate the select items for the 2nd menu. The otherMenuId must refer to id of the other <h:selectOneMenu> in the same <a4j:region>.
You have to define a valueChangeListener for your first selectOneMenu:
<h:selectOneMenu id="select1" valueChangeListener="#{myBean.updateSections}">
<f:selectItems value="#{myBean.sections1}" />
</h:selectOneMenu>
Inside MyBean#updateSections you have to modify the list of SelectItems the second selectOneMenu has to show according to the selection you made.
Furthermore you have to submit your form or rerender section2 to display the updated values in section2.

<h:selectOneMenu> with temporary disabled SelectItems

I have a <h:selectOneMenu> that renders the value of the cardStatus from my object model.
A CardStatus has an boolean attribute 'temporaryDisabled' that means that the value is still valid but should not be used by the user.
Now, if my model has cardStatus set to a temporary disabled value, how can I show this value in the dropdown combobox and still prevent the user from changing the value to another temporary disabled status?
If I just delete the disabled card statuses from the list of SelectItems that I feed to <h:selectOneMenu> then when the select gets rendered it will automatically select the first item in the list an submit it next time consequently wrongly changing my value in the model.
If I include the disabled card statuses in the list of SelectItems but set the value of the disabled attribute to true for their corresponding items, they are rendered in HTML disabled and not submitted so I get a null value in my model which is also wrong.
I am stuck. Any advice is kindly appreciated.
Best regards,
Dan.
Finally what I did was to use a piece of jQuery code that gets executed after the page is loaded.
<h:selectOneMenu
id="cardStatus"
value="#{someBean.cardStatus}"
converter="selectItemConverter">
<f:selectItem itemValue="E|A" itemLabel="Active" />
<f:selectItem itemValue="E|S" itemLabel="Stolen" />
<f:selectItem itemValue="D|B" itemLabel="Blocked" />
<f:selectItem itemValue="E|L" itemLabel="Lost" />
<f:selectItem itemValue="D|C" itemLabel="Counterfeit" />
</h:selectOneMenu>
What the javascript code does is to scan all the items and for each item with a value starting with the prefix D| hide the item using jQuery's hide() function. This way the combobox is acting as all values would be valid/enabled, but the user will not be able to select inactive values because they are not visible. Furthermore, if the default selected value is one of the values starting with D|, the value will still be shown as default value but the user is not able to see it in the list of options he/she can choose from.
"that means that the value is still valid but should not be used by the user"
Help me understand this piece. You want to display these choices in an h:selectOneMenu but not allow the user to select them? I guess I don't understand why you would present them to the user if they are invalid options for them?
You could always create a validator that validates against "temporaryDisabled" if that's what you're trying to accomplish ... let me know more about what you want the end-user to see and I can probably help.
<h:selectOneMenu
id="cardStatus"
value="#{someBean.cardStatus}"
converter="selectItemConverter">
<f:selectItem itemValue="#{null}" itemLabel="" />
<f:selectItems
value="#{cardStatusBean.cardStatuses}"
var="cardStatus"
itemValue="#{cardStatus}"
itemLabel="#{cardStatus.name}"
itemDisabled="#{cardStatus.temporaryDisabled}"/>
</h:selectOneMenu>
This would give you a default choice with a value of null and an empty label. Would that accomplish what you are looking for?
For the record, if using JSF 2.0, f:selectItem and f:selectItems have an "itemDisabled" attribute that produces the desired behavior.

JSF - Populating a drop down depending on value in other drop down

I need to populate a drop down based on the selected value in another drop down. I can use AJAX requests to do that but I am searching for a solution using JSF only. The values to populate the drop down need to come from a table every time user changes his selection.
Thanks
You didn't specify the version, so I'll assume JSF 1.2. The <a4j:support> tag is part of RichFaces:
<h:selectOneMenu id="firstDropDown" value="#{bean.firstDropDownSelection}">
<f:selectItems value="#{bean.items}" />
<a4j:support event="onchange" reRender="secondDropDown"
immediate="true" action="#{bean.fetchItems2}" />
</h:selectOneMenu>
<h:selectOneMenu id="secondDropDown" value="#{bean.secondDropDownSelection}">
<f:selectItems value="#{bean.items2}" />
</h:selectOneMenu>
And in the method bean.fetchItems2 you load your collection items2 with the appropriate items.
What happens, is when the value of the first drop down changes, the second drop down is rerendered and its value is fetched from the server again.

Resources