2011-01-04 32 views
6

Trong một trang "tạo người dùng mới" JSF, tôi có một SelectOneMenu với bộ chuyển đổi tùy chỉnh và một selectItem noSelectionOption như thế này: (mã không liên quan Bỏ qua phần)JSF SelectOneMenu with noSelectionOption sử dụng nhãn làm giá trị?

NewUser.xhtml

<h:form> 
<h:selectOneMenu value="#{newUserController.user.department}" 
       required="true" converter="departmentConverter"> 
    <f:selectItem itemLabel="Select a department" noSelectionOption="true"/> 
    <f:selectItems value="#{newUserController.departments}" 
        var="dep" itemLabel="#{dep.name}" itemValue="#{dep}"/> 
</h:selectOneMenu> 
<p:commandButton action="#{newUserController.saveUser}" 
       value="#{bundle.Save}" 
       ajax="false"/> 
</h:form> 

NewUserController.java

@ManagedBean 
@ViewScoped 
public class NewUserController implements Serializable { 
private static final long serialVersionUID = 10L; 

@EJB private UserBean userBean; 
private List<Department> departments; 
private User user; 

public NewUserController() { 
} 

@PostConstruct 
public void init(){ 
    user = new User(); 
    departments = userBean.findAllDepartments(); 
} 

public User getUser() { 
    return user; 
} 

public void setUser(User user) { 
    this.user = user; 
} 

public List<Department> getDepartments(){ 
    return departments; 
} 

public String saveUser() { 
    // Business logic 
} 
} 

DepartmentConverter.java

@FacesConverter(value="departmentConverter") 
public class DepartmentConverter extends EntityConverter { 
    public DepartmentConverter(){ 
     super(Department.class); 
    } 
} 

Siêu chuyển đổi cho tất cả các đơn vị

public class EntityConverter<E> implements Converter{ 
protected Class<E> entityClass; 

public EntityConverter(Class<E> type) { 
    entityClass = type; 
} 

@Override 
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) { 
    if (value == null || value.length() == 0) { 
     return null; 
    } 
    try { 
     InitialContext ic = new InitialContext(); 
     UserBean ub = (UserBean)ic.lookup("java:global/CompetenceRegister/UserBean"); 
     return ub.find(entityClass, getKey(value)); 
    } catch (NamingException e) { 
     return null; 
    } 
} 

Long getKey(String value) { 
    Long key; 
    key = Long.valueOf(value); 
    return key; 
} 

String getStringKey(Long value) { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(value); 
    return sb.toString(); 
} 

@Override 
public String getAsString(FacesContext facesContext, UIComponent component, Object object) { 
    if (object == null) { 
     return null; 
    } 
    if (object instanceof AbstractEntity) { 
     AbstractEntity e = (AbstractEntity) object; 
     return getStringKey(e.getId()); 
    } 
    else 
     throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + entityClass.getName()); 
} 

}

Tuy nhiên, khi tôi đăng các hình thức với tùy chọn "Chọn một bộ phận" được lựa chọn, nó sẽ gửi nhãn để getAsObject trong bộ chuyển đổi thay vì null , do đó gây ra trình biến đổi để ném một ngoại lệ trong getKey (cố gắng chuyển đổi một String chứa một id thành Long). Đặt thuộc tính itemValue của selectItem thành null không có hiệu lực. Các mục từ bộ sưu tập hoạt động hoàn hảo với bộ chuyển đổi. Có ai có bất kỳ ý tưởng về những gì đang gây ra điều này?

Cập nhật Điều thú vị mà tôi quên đề cập đến; nếu tôi loại bỏ thuộc tính chuyển đổi khỏi SelectOneMenu, thuộc tính noSelectionAttribute hoạt động như nó cần, nhưng vì trình biến đổi mặc định không biết cách chuyển đổi các đối tượng của tôi, nên bài đăng không thành công khi chọn một bộ phận thực. Điều này có nghĩa là noSelectionOption = true là SUPPOSED để gửi nhãn của nó thay thế và trình chuyển đổi bằng cách nào đó được mong đợi sẽ xử lý nó?

+0

Đây có phải là jsf1 hoặc jsf2 không? –

+0

Sử dụng Jsf 2. Xin lỗi vì không làm rõ. –

+1

@Shervin: 'f: selectItem noSelectionOption' và' f: selectItems var' biểu thị JSF2. – BalusC

Trả lời

7

Sự cố của tôi đã chuyển sang sử dụng thuộc tính chuyển đổi của SelectOneMenu thay vì sử dụng thuộc tính forClass của FacesConverter.

chuyển

@FacesConverter(value="departmentConverter") 
public class DepartmentConverter extends EntityConverter { 
public DepartmentConverter(){ 
    super(Department.class); 
} 
} 

để

@FacesConverter(forClass=Department.class) 
public class DepartmentConverter extends EntityConverter { 
public DepartmentConverter(){ 
    super(Department.class); 
} 
} 

gây chuyển đổi của riêng tôi để được sử dụng cho các giá trị thực trong khi chuyển đổi mặc định (null chuyển đổi? Tôi đã không thể tìm ra mã nguồn cho nó) được sử dụng khi thuộc tính NoSelectionOption được đặt thành true. Lý thuyết của tôi là thiết lập thuộc tính này thành true đặt kiểu giá trị là null với nhãn là giá trị khiến nó đi tới một công cụ chuyển đổi đặc biệt luôn trả về null hoặc một cái gì đó tương tự. Sử dụng thuộc tính converter thay vì forClass làm cho công cụ chuyển đổi của riêng tôi luôn được sử dụng bất kể loại, và do đó tôi sẽ phải xử lý nhãn được gửi dưới dạng giá trị.

+1

Câu trả lời này rất khó hiểu: đoạn đầu tiên biểu thị sự thay đổi theo hướng ngược lại chính xác như được gợi ý sau. –

1

Một giải pháp mà các công trình là chỉ cần thêm

try{ 
    return ub.find(entityClass, getKey(value)); 
}catch(NumberFormatException e){ // Value isn't a long and thus not an id. 
    return null; 
} 

đến getAsObject trong EntityConverter, nhưng điều này cảm thấy như tôi đang sửa chữa các vấn đề ở địa điểm sai. Việc gửi nhãn dưới dạng giá trị đơn giản là không có ý nghĩa, nó thực sự phải gửi NULL.

Các vấn đề liên quan