【问题标题】:JSF SelectOneMenu with noSelectionOption using label as value?使用标签作为值的带有 noSelectionOption 的 JSF SelectOneMenu?
【发布时间】:2011-01-04 15:27:03
【问题描述】:

在“创建新用户”jsf 页面中,我有一个带有自定义转换器的 SelectOneMenu 和一个 noSelectionOption selectItem,如下所示:(省略了不相关的代码)

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);
    }
}

所有实体的超级转换器

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());
}

}

但是,当我发布带有“选择部门”选项的表单时,它会将 label 发送到转换器中的 getAsObject 而不是 null,从而导致转换器在 getKey 中引发异常(尝试将包含 id 的 String 转换为 Long)。将 selectItem 的 itemValue 属性设置为 null 无效。该系列中的物品可以与转换器完美配合。有人知道是什么原因造成的吗?

更新 一件我忘了提的有趣的事;如果我从 SelectOneMenu 中删除转换器属性,则 noSelectionAttribute 可以正常工作,但是由于默认转换器不知道如何转换我的对象,因此帖子无法选择真正的部门。这是否意味着 noSelectionOption=true 是 SUPPOSED 发送它的标签,而转换器应该以某种方式处理它?

【问题讨论】:

  • 使用 Jsf 2。抱歉没有澄清。
  • @Shervin: f:selectItem noSelectionOptionf:selectItems var 表示 JSF2。
  • 您的 facelet 标记似乎正确。为你的部门转换器和你的 newUserController 包含代码怎么样?
  • 我没有包含转换器,因为它感觉无关紧要,因为问题在于如何调用它而不是它自己的功能,并且控制器非常简单。但是我已经更新了帖子,所以你现在可以看到几乎所有内容。

标签: jsf jsf-2 converter selectonemenu


【解决方案1】:

我的问题是切换到使用 SelectOneMenu 的转换器属性,而不是使用 FacesConverter 的 forClass 属性。

切换

@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);
}
}

当 NoSelectionOption 属性设置为 true 时,我自己的转换器用于实数值,而默认转换器(空转换器?我无法找到它的源代码)使用。我的理论是,将此属性设置为 true 会将值的类型设置为 null ,并将标签作为值,导致它转到始终返回 null 或类似内容的特殊转换器。使用转换器属性而不是 forClass 会导致始终使用我自己的转换器,而不管类型如何,因此我必须自己处理作为值发送的标签。

【讨论】:

  • 这个答案令人困惑:第一段表示与后面所建议的方向完全相反的变化。
【解决方案2】:

一个可行的解决方案是简单地添加

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

到 EntityConverter 中的 getAsObject,但这感觉就像我在错误的地方解决了问题。将标签作为值发送根本没有意义,它应该真正发送 NULL。

【讨论】:

    猜你喜欢
    • 2011-05-31
    • 2021-11-22
    • 1970-01-01
    • 2013-05-29
    • 2012-05-04
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 2015-11-24
    相关资源
    最近更新 更多