20

I am working on a JSF page which has a dropdown based on List<SelectItem>:

<h:selectOneMenu value="#{bean.selectedItem}">
    <f:selectItems value="#{bean.availableItems}" />
</h:selectOneMenu>

I need to get both the value and label of the currently selected item. Right now I only get the value. How can I get the label, too?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
SomeFatMan
  • 397
  • 2
  • 4
  • 15

5 Answers5

49

You can't. That's just how HTML works. You know, JSF is a HTML code generator. The JSF <h:selectOneMenu> generates a HTML <select><option> . The HTML <select> element will only send the value attribute of the selected <option> element. It will not send its label.

But that shouldn't be a big issue. You namely already know both the value and label in the server side, inside the #{bean.availableItems}. All you need to do to get the associated label is to get it by the value as key. I suggest to make it a Map which in turn can also be used in f:selectItems.

Basic kickoff example:

public class Bean {
    private String selectedItem; // +getter +setter
    private Map<String, String> availableItems; // +getter

    public Bean() {
        availableItems = new LinkedHashMap<String, String>();
        availableItems.put("value1", "label1");
        availableItems.put("value2", "label2");
        availableItems.put("value3", "label3");
    }

    public void submit() {
        String selectedLabel = availableItems.get(selectedItem);
        // ...
    }
}

with

<h:selectOneMenu value="#{bean.selectedItem}">
    <f:selectItems value="#{bean.availableItems.entrySet()}" var="entry"
        itemValue="#{entry.key}" itemLabel="#{entry.value}" />
</h:selectOneMenu>

and in result

<p>Selected label is #{bean.availableItems[bean.selectedItem]}</p>

An alternative is to wrap both name and value in a javabean object representing an entity and set the whole object as value, via a converter.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • `availableItems.put("value1", "label1");` Should be `availableItems.put("label1", "value1");` If you want that label to be like: "label1" and value: "value1" – roadev Mar 16 '17 at 14:50
  • 1
    @roadev only when you don't use the given `` example. But then this completely defeats the initial question: being able to get label by value. Your approach would make it impossible again. Perhaps you forgot to read the question? – BalusC Mar 16 '17 at 14:57
4

Instead of Using Map I tried like this and it's perfectly working for me to get both ItemValue and ItemLabel in the same property by using "ItemValue" attribute in selectItems tag.How ever provided no extra commas in the ItemLabel(@asfas....i had the same problem u mentioned so i selected this approach).

<h:selectOneMenu  value="#{company.issueDesc}"   required="true" onchange="submit()">
     <f:selectItem itemLabel="-- Select a Issue -- " itemValue="0"/>  
     <f:selectItems value="#{company.issueList}" var="model" itemLabel="#{model.IssueDesc}" itemValue="#{model.Code},#{model.IssueDesc}" >
      </f:selectItems>
</h:selectOneMenu>

Basically IssueDesc is String type in Bean Company

    public Class Company{

      private String issueDesc;    // getters and setters
      private int code;  // getters and setters
      private List<T>issueList; // getters and setters.


         public void getLblandVal(){

           String desc=getIssueDesc();
           String[] str_ary=desc.split(",");
           String s1=str_ary[0];
           String s2=str_ary[1];
          // parse **s1** to int;
    }


}
mdp
  • 815
  • 4
  • 17
  • 32
3

What if the the value should be Integer and label String and both are needed in backing bean. Using Map in bean doesn't work because JSF interprets the map key as label. Ideally it would be a LinkedHashMap and search the text by a number.

Seems upside down to search number (value) by a text (key). What if some implementation of JSF adds extra space to test or letter case changes for some reason. Then the value is not found from map.

asfas
  • 31
  • 1
2

This will do the trick.

private String getLabel(List<SelectItem> list, String selection) {
    String label = "";
    for (int i = 0; i < list.size(); i++) {
        if(selection.equals((String)list.get(i).getValue())) {
            label = (String)list.get(i).getLabel();
            break;
        }
    }

    return label;
}

In your example, you would pass in the availableItems as 'list' and selectedItem as 'selection'. This method will return the label value corresponding to the selectedItem.

J. Van
  • 190
  • 1
  • 17
  • Please add this to the accepted answer. It is a (slight) enhancement/extension of it and by itself it is pure code without any explanation. – Kukeltje Mar 29 '18 at 18:08
  • 1
    Why was this downvoted? It would be nice to know if I wrote something incorrect to let me know what it was. Looks like Kukeltje accepted it as an accepted answer. As far as I'm concerned, the code has been tested and is in use with no issues. So, I'd really like some feedback on the downvote. – J. Van Apr 02 '18 at 16:29
  • 3 Reasons I think. When you look at it, it you posted just getting the label without any context and even that part is a lot more complex then in the accepted and 40 upvote answer. And thirdly, using the SelectItem class in jsf is recent times (since jsf2) sort of not needed anymore. So it is kind of old-school – Kukeltje Apr 02 '18 at 18:00
  • 1
    Good enough. But...I did answer the question directly. The question was about SelectItem, So, the answer fit the question. I still don't see why it was downvoted as opposed to simply left at 0. The answer is correct. But, thank you for your response. I always appreciate a learning moment. – J. Van Apr 04 '18 at 12:10
  • 1
    the code provided in the answer is working correctly. may be it's not really elegant solution but doing exactly what asked. not sure why it was down-voted – David Abragimov Oct 18 '18 at 15:57
1

The following approach may also be useful in getting value and label using List <SelectItem>:
Here, facade, statesFacade fetches list of states from database/enterprise bean.

In view (xhtml page):

    <h:selectOneMenu id="statesSelectUi" value="#{applicationBean1.state}">
        <f:selectItems value="#{applicationBean1.stateSelectItems}"/>
        <f:ajax render="selectedItem" event="change" execute="statesSelectUi"/>
    </h:selectOneMenu>
    <br/>
    <br/>
    <h:outputText id="selectedItem" value="#{applicationBean1.selectedState}"/>

In the Managed Bean(applicationBean1.java):

private String state;

/**
     * @return the stateSelectItems
     */
    public List<SelectItem> getStateSelectItemsItems() {
        stateSelectItems.add(new SelectItem("-1","--- Select state ---"));
        int statesCount = statesFacade.count();
        List<StateSelectItems> states;
        states = statesFacade.findAll();
        for (int i = 0; i < statesCount; i++) {
            stateSelectItems.add(new SelectItem(states.get(i).getStateSlNo(), states.get(i).getStateName()));
        }
        return stateSelectItems;
    }


       public String getSelectedState(){
       if("".equals(getState()) || getState() ==null){
        return "";
       }else{
        return "Selected State : " + getStateSelectItems.get(Integer.parseInt(getState())).getValue()+", "++ getStateSelectItems.get(Integer.parseInt(getState())).getLabel();
       }
    }
AVA
  • 2,474
  • 2
  • 26
  • 41