0

我有一个 selectOneMenu,它控制数据表中应该显示的内容。代码如下(我已经删除了所有不必要的人员):

<ui:composition template="/WEB-INF/templates/BasicTemplate.xhtml">
  <ui:define name="content">
    <br />
    <h:form id="menuform">

      <p:selectOneMenu value="#{envMenuBean.currentEnvName}">
        <f:selectItems value="#{envMenuBean.envs}" var="env" itemLabel="#{env.name}" itemValue="#{env.name}" />
        <p:ajax event="change" update="currentEnvoutput,contentpanel" listener="#{envMenuBean.envChange}" />
      </p:selectOneMenu>

      <h:outputLabel value="Current Selection: " />
      <h:outputText id="currentEnvoutput" style="font-weight:bold" value="#{envMenuBean.currentEnvName}"></h:outputText>

      <br />
      <p:panel id="contentpanel">
        <div id="contentdiv">
          <p:dataTable id="gcfiletable" var="row" value="#{gCSelectionBean.dataTableDTO.serverListRows}">
            <p:column>
              <f:facet name="header">
                <h:outputText value="Server Names" />
              </f:facet>
              <h:outputText value="#{row.serverName}" />
            </p:column>
            <p:columns value="#{gCSelectionBean.dataTableDTO.machineNamesList}" var="columnName" columnIndexVar="colIndex">
              <f:facet name="header">  
                #{columnName}  
              </f:facet>
            </p:columns>
          </p:dataTable>
        </div>
      </p:panel>

    </h:form>
  </ui:define>
</ui:composition>

envMenuBean.envChange 代码非常简单:

@ManagedBean
@SessionScoped
public class EnvMenuBean {
  private String currentEnvName;    

  public void envChange(AjaxBehaviorEvent event) {
    String newValue = (String)((UIOutput)event.getSource()).getValue();
    currentEnvName = newValue;
  }
}

数据表内容在 gCSelectionBean 类中生成:

@ManagedBean
@SessionScoped
public class GCSelectionBean {
  private GCInstanceDataTableDTO dataTableDTO;  
  String currentEnvName;

  public GCInstanceDataTableDTO getDataTableDTO() {
    FacesContext fc = FacesContext.getCurrentInstance();
    Application app = fc.getApplication();
    ExpressionFactory exp = app.getExpressionFactory();

    ValueExpression currEnvNameMenuBeanEL = exp.createValueExpression(fc.getELContext(), "#{envMenuBean.currentEnvName}", String.class);
    String currEnvNameMenuBean = (String) currEnvNameMenuBeanEL.getValue(fc.getELContext());    

    ApplicationConfigs gcReportConfigs = GetAppConfigs.getInstance().getAppConfigs();
    for (Environment env : gcReportConfigs.getEnvs()) {
      if (env.getName().equalsIgnoreCase(currEnvNameMenuBean)) {         
        dataTableDTO = new GCInstanceDataTableDTO(env);
        currentEnvName = currEnvNameMenuBean;
        break;
      }
    }

    return dataTableDTO;
  }  
}

然而代码

    ValueExpression currEnvNameMenuBeanEL = exp.createValueExpression(fc.getELContext(), "#{envMenuBean.currentEnvName}", String.class);
    String currEnvNameMenuBean = (String) currEnvNameMenuBeanEL.getValue(fc.getELContext());    

给了我更改前的旧 selectOneMenu 值,这使我的数据表仍然显示旧表值。但是

<h:outputText id="currentEnvoutput" style="font-weight:bold" value="#{envMenuBean.currentEnvName}"></h:outputText>

可以显示正确的新值。

这让我相信 myfaces 在处理 ajax 更改事件之前首先呈现表格。当我将 JSF2.0 实现从 myfaces 更改为 Glassfish 时,相同的代码运行良好。

有没有人遇到过同样的问题?如何解决这个问题?

4

2 回答 2

1

实际上更新currentEnvName的值应该出现在

public void envChange(AjaxBehaviorEvent event) {
    System.out.println(currentEnvName );
}

你不必像你一样设置它......

而不是所有这些ValueExpression东西,您最好使用托管属性在您的内部GCSelectionBean添加以下内容:

@ManagedProperty(value = "#{envMenuBean }")
private EnvMenuBean envMenuBean ; //add getter and setter

currentEnvName从 envMenuBean 对象访问...

就这样 ?

于 2012-10-22T06:58:46.253 回答
0

这似乎是 primefaces 的问题,将 primefaces 从 primefaces-3.4-SNAPSHOT 升级到 primefaces-3.4.1 后,问题得到解决。

于 2012-10-23T02:46:23.887 回答