2011-11-22 13 views
83

Tôi muốn tạo dropOneMenu thả xuống để tôi có thể chọn trạng thái trên câu hỏi của mình. Có thể làm cho f: selectItem linh hoạt hơn khi xem xét điều gì xảy ra nếu thứ tự của enums thay đổi và nếu danh sách lớn? Và tôi có thể làm điều này tốt hơn không? Và có thể tự động "chọn" mục mà câu hỏi có?Cách sử dụng các giá trị enum trong f: selectItem (s)

Enum lớp

public enum Status { 
    SUBMITTED, 
    REJECTED, 
    APPROVED 
} 

Câu hỏi thực thể

@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> 

Trả lời

172

JSF có một chuyển đổi BUILTIN cho enum, vì thế này nên làm:

@ManagedBean 
@ApplicationScoped 
public class Data { 

    public Status[] getStatuses() { 
     return Status.values(); 
    } 

} 

với

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

(lưu ý: kể từ JSF 2.0 không cần nữa để cung cấp một SelectItem[] hoặc List<SelectItem>, a T[]List<T> cũng được chấp nhận và bạn có thể truy cập mục hiện tại theo thuộc tính var)

Nếu bạn tình cờ sử dụng thư viện tiện ích JSF OmniFaces, thì bạn có thể sử dụng <o:importConstants> thay vì đậu.

<o:importConstants type="com.example.Status" /> 

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

Nếu bạn có ý định để kiểm soát các nhãn là tốt, bạn có thể thêm chúng vào 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; 
    } 

} 

với

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

Hoặc, tốt hơn, làm cho giá trị enum một khóa thuộc tính của gói tài nguyên được bản địa hóa (yêu cầu EL 3.0):

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

với điều này trong một tập tin tài sản gắn liền với bó tài nguyên #{text}

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

Một điều BalusC, có thể "chọn"/xem trạng thái mà câu hỏi có mặc định hay không (ví dụ khi bạn đang chỉnh sửa câu hỏi thì bạn đã đặt trạng thái của câu hỏi thành câu hỏi) – LuckyLuke

+0

Trong ví dụ trên , JSF sẽ làm điều đó theo mặc định khi '# {bean.question.status}' có giá trị enum hợp lệ. Bạn không cần phải làm bất cứ điều gì mong đợi để đảm bảo rằng 'câu hỏi' có thuộc tính trạng thái thích hợp được điền sẵn. – BalusC

+0

Ồ, okey. Hiểu rồi! :) – LuckyLuke

3

Bạn có thể sử dụng <f:selectItems value="#{carBean.carList}" /> và trả về danh sách các trường hợp SelectItem bao bọc enum (sử dụng Status.values() để nhận tất cả các giá trị có thể).

14

Đối nội địa hóa chúng ta có thể sử dụng cũng giải pháp này:

public enum Status { SUBMITTED, REJECTED, APPROVED } 

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

<h:selectOneMenu value="#{bean.question.status}" > 
    <f:selectItems 
     value="#{data.statuses}" 
     var="status" 
     itemValue="#{status}" 
     itemLabel="#{text['data.status.'.concat(status)]}" /> 
</h:selectOneMenu> 

Vì vậy, con đường tài nguyên cho các chuỗi nội địa hóa không hardcoded trong Enum.

+1

Lưu ý rằng cú pháp này chỉ được hỗ trợ từ EL 2.2 là "tương đối" mới. Nếu không, bạn luôn có thể lấy ' 'hoặc' ' hoặc homebrew một chức năng EL tùy chỉnh. – BalusC

+0

Cảm ơn bạn BalusC. Có thể bằng cách nào đó thay thế # {data.statuses} bằng Lớp enum mà không sử dụng bean sao lưu (ví dụ: value = "# {org.myproject.Status.values}") không? – Ziletka

+0

@BalusC bạn có chắc chắn không? Tôi đang sử dụng GF 3.1.2 (Mojarra JSF 2.1.6). – Ziletka

1

Bạn có thể sử dụng hàm el tiện ích sau để lấy giá trị enum và sử dụng chúng trong ví dụ SelectOneMenu. Không cần phải tạo đậu và phương pháp boilerplate.

public final class ElEnumUtils 
{ 
    private ElEnumUtils() { } 

    /** 
    * Cached Enumerations, key equals full class name of an enum 
    */ 
    private final static Map<String, Enum<?>[]> ENTITY_ENUMS = new HashMap<>();; 

    /** 
    * Retrieves all Enumerations of the given Enumeration defined by the 
    * given class name. 
    * 
    * @param enumClassName Class name of the given Enum. 
    * 
    * @return 
    * 
    * @throws ClassNotFoundException 
    */ 
    @SuppressWarnings("unchecked") 
    public static Enum<?>[] getEnumValues(final String enumClassName) throws ClassNotFoundException 
    { 
     // check if already cached - use classname as key for performance reason 
     if (ElEnumUtils.ENTITY_ENUMS.containsKey(enumClassName)) 
      return ElEnumUtils.ENTITY_ENUMS.get(enumClassName); 

     final Class<Enum<?>> enumClass = (Class<Enum<?>>) Class.forName(enumClassName); 

     final Enum<?>[] enumConstants = enumClass.getEnumConstants(); 

     // add to cache 
     ElEnumUtils.ENTITY_ENUMS.put(enumClassName, enumConstants); 

     return enumConstants; 
    } 
} 

đăng ký nó như là một chức năng el trong một file taglib:

<function> 
    <description>Retrieves all Enumerations of the given Enumeration defined by the given class name.</description> 
    <function-name>getEnumValues</function-name> 
    <function-class> 
     package.ElEnumUtils 
    </function-class> 
    <function-signature> 
     java.lang.Enum[] getEnumValues(java.lang.String) 
    </function-signature> 
</function> 

Và cuối cùng gọi nó thích:

<p:selectOneMenu value="#{bean.type}"> 
    <f:selectItems value="#{el:getEnumValues('package.BeanType')}" var="varEnum" 
     itemLabel="#{el:getEnumLabel(varEnum)}" itemValue="#{varEnum}"/> 
</p:selectOneMenu> 

tương tự để BalusC trả lời bạn nên sử dụng một gói tài nguyên với nhãn enum được bản địa hoá và để có mã sạch hơn, bạn cũng có thể tạo một hàm như getEnumLabel(enum)

+0

Không cần một "hàm" (phương thức khác), khi bạn có thể sử dụng '# {myBundle [enumName.i18nKey]}' và sau đó đặt các khóa i18n vào liệt kê của bạn dưới dạng thuộc tính: 'BLA_TYPE (" SOME_BLA_TYPE_KEY ")' bởi 'BLA_TYPE' là enum được sử dụng và' SOME_BLA_TYPE_KEY' là khóa i18n. – Roland