Java p:SelectOne菜单值设置为空,当在刷新的选项卡视图中处于p:inplace时

Java p:SelectOne菜单值设置为空,当在刷新的选项卡视图中处于p:inplace时,java,jsf,primefaces,Java,Jsf,Primefaces,我正在使用p:tabView将可编辑数据拆分为多个部分。所有编辑元素都位于p:inplace组件内。问题具体在于p:selectOneMenu组件 刷新整个选项卡视图时,其他选项卡上活动的p:selectOneMenu的值设置为空。我不知道为什么。这是一个bug,还是错误地使用了PrimeFaces组件 环境: PrimeFaces 3.4 MyFaces 2.0.7 IBM WebSphere 7.0 重现错误的方法: 创建包含多个选项卡的选项卡视图 将selectOneMenu置于一个

我正在使用
p:tabView
将可编辑数据拆分为多个部分。所有编辑元素都位于
p:inplace
组件内。问题具体在于
p:selectOneMenu
组件

刷新整个选项卡视图时,其他选项卡上活动的
p:selectOneMenu
的值设置为空。我不知道为什么。这是一个bug,还是错误地使用了PrimeFaces组件

环境:

  • PrimeFaces 3.4
  • MyFaces 2.0.7
  • IBM WebSphere 7.0
重现错误的方法:

  • 创建包含多个选项卡的选项卡视图
  • 将selectOneMenu置于一个选项卡中的inplace内
  • “生成”按钮将更新选项卡视图
  • 选择selectOneMenu的值,更改选项卡,单击“刷新”,然后使用selectOneMenu返回选项卡
示例页面和bean的代码:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
   xmlns:ui="http://java.sun.com/jsf/facelets"
   xmlns:f="http://java.sun.com/jsf/core"
   xmlns:h="http://java.sun.com/jsf/html"
   xmlns:p="http://primefaces.org/ui">
<h:head>
   <f:facet name="first">
      <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
   </f:facet>
   <title>QMWPSUI</title>
   <h:outputScript library="qm" name="qmutils.js" />
   <h:outputScript library="qmwpsui" name="process.js" />
</h:head>
<h:body>


<h:form id="main">
   <p:blockUI block="main" trigger="refreshButton" widgetVar="block">
   <p:graphicImage
            value="#{resource['primefaces-qmui:images/waitprogress.gif']}" />
   </p:blockUI> 

   <h3>Test</h3>

      <p:commandButton id="refreshButton" widgetVar="refreshButton"
               action="#{test.refresh}" 
               icon="ui-icon-refresh"   title="#{i18n['action.reload']}"
               onclick="block.show()"
               update="tabView"/>

      <p:tabView id="tabView" orientation="top" dynamic="TRUE">
         <p:tab id="tab1" title="Tab 1" process="@this">
            <h:outputLabel value="Type*:" for="type"/>
            <p:inplace emptyLabel="Click here to change">
               <p:selectOneMenu id="typ" value="#{test.type}" effect="fade"
                  style="width:300px">
                  <f:selectItem itemLabel="" itemValue="" />
                  <f:selectItem itemLabel="Type a" itemValue="a" />
                  <f:selectItem itemLabel="Type b" itemValue="b" />
                  <f:selectItem itemLabel="Type c" itemValue="c" />
               </p:selectOneMenu>
            </p:inplace>
         </p:tab>
         <p:tab id="tab2" title="Tab 2" process="@this">
         </p:tab>
         <p:tab id="tab3" title="Tab 3" process="@this">
         </p:tab>
      </p:tabView>      

</h:form>

</h:body>

QMWPSUI
试验
bean类:

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean(name = "test")
@ViewScoped
public class TestBean implements Serializable {

   private static final long serialVersionUID = 1L;

   private static final Logger log = LoggerFactory.getLogger(TestBean.class);
   private String type;

   public String getType() {
      return type;
   }

   public void setType(String type) {
      this.type = type;
   }

   @Override
   public String toString() {
      StringBuilder builder = new StringBuilder();
      builder.append("TestBean [");
      if (type != null) {
         builder.append("type=");
         builder.append(type);
      }
      builder.append("]");
      return builder.toString();
   }

   public void refresh() {
      log.info("Refresh");
      log.info("Test = <{}>", this);
   }

}
import java.io.Serializable;
导入javax.faces.bean.ManagedBean;
导入javax.faces.bean.ViewScoped;
@ManagedBean(name=“test”)
@视域
公共类TestBean实现了可序列化{
私有静态最终长serialVersionUID=1L;
私有静态最终记录器log=LoggerFactory.getLogger(TestBean.class);
私有字符串类型;
公共字符串getType(){
返回类型;
}
公共void集合类型(字符串类型){
this.type=type;
}
@凌驾
公共字符串toString(){
StringBuilder=新的StringBuilder();
append(“TestBean[”);
if(type!=null){
builder.append(“type=”);
builder.append(类型);
}
生成器。追加(“]”);
返回builder.toString();
}
公共无效刷新(){
日志信息(“刷新”);
log.info(“Test=”,this);
}
}

这种情况下需要一个转换器

公共类EmptyToNullConverter实现转换器{

@Override
public Object getAsObject(FacesContext facesContext, UIComponent component,
        String value) {
    Object retorno = value;
    if (value == null || value.isEmpty()) {
        if (component instanceof EditableValueHolder) {
            ((EditableValueHolder) component).setSubmittedValue(null);
        }
        retorno = null;
    }
    return retorno;
}

@Override
public String getAsString(FacesContext facesContext, UIComponent component,
        Object value) {
    return (value == null) ? null : value.toString();
}
}

并在faces-config.xml中定义

<converter>
    <converter-for-class>java.lang.String</converter-for-class>
    <converter-class>org.converter.EmptyToNullConverter</converter-class>
</converter>

java.lang.String
org.converter.EmptyToNullConverter

为了使情况更一般,似乎也会发生在
上,而没有
。可能与此有关?除了不使用动态选项卡之外,还有其他解决方案吗?一个解决方法是在setter中测试
null
,如果
null
不更改
type
的值。我看不出它如何修复该行为此转换器解决了此处描述的完全不同的问题: