jsfjsf-2enumsselectonemenu

How to use enum values in f:selectItem(s)


I want to make a selectOneMenu dropdown so I can select a status on my question. Is it possible to make the f:selectItem more flexible considering what happens if the order of the enums changes, and if the list was large? And could I do this better? And is it possible to automatically "select" the item that the question have?

Enum class

public enum Status {
    SUBMITTED,
    REJECTED,
    APPROVED
}

Question entity

@Enumerated(EnumType.STRING)
private Status status;

JSF

<div class="field">
    <h:outputLabel for="questionStatus" value="Status" />
    <h:selectOneMenu id="questionStatus" value="#{bean.question.status}" >
        <f:selectItem itemLabel="Submitted" itemValue="0" />
        <f:selectItem itemLabel="Rejected" itemValue="1" />
        <f:selectItem itemLabel="Approved" itemValue="2" />
    </h:selectOneMenu>
    <hr />
</div>

Solution

  • JSF has a builtin converter for enum, so this should do:

    @Named
    @ApplicationScoped
    public class Data {
    
        public Status[] getStatuses() {
            return Status.values();
        }
    
    }
    

    with

    <h:selectOneMenu value="#{bean.question.status}" >
        <f:selectItems value="#{data.statuses}" />
    </h:selectOneMenu>
    

    (note: since JSF 2.0 there's no need anymore to provide a SelectItem[] or List<SelectItem>, a T[] and List<T> are accepted as well and you can access the current item by var attribute)

    If you happen to use JSF utility library OmniFaces, then you could use <o:importConstants> instead of a bean.

    <o:importConstants type="com.example.Status" />
    
    <h:selectOneMenu value="#{bean.question.status}" >
        <f:selectItems value="#{Status}" />
    </h:selectOneMenu>
    

    If you intend to control the labels as well, you could add them to the Status enum:

    public enum Status {
    
        SUBMITTED("Submitted"),
        REJECTED("Rejected"),
        APPROVED("Approved");
    
        private String label;
    
        private Status(String label) {
            this.label = label;
        }
    
        public String getLabel() {
            return label;
        }
    
    }
    

    with

    <f:selectItems value="#{data.statuses}" var="status"
        itemValue="#{status}" itemLabel="#{status.label}" />
    

    Or, better, make the enum value a property key of a localized resource bundle (EL 3.0 required):

    <f:selectItems value="#{data.statuses}" var="status"
        itemValue="#{status}" itemLabel="#{text['data.status.' += status]}" />
    

    with this in a properties file associated with resource bundle #{text}

    data.status.SUBMITTED = Submitted
    data.status.REJECTED = Rejected
    data.status.APPROVED = Approved