【问题标题】:JSF El expression retaining old value (JSF life cycle)JSF El 表达式保留旧值(JSF 生命周期)
【发布时间】:2012-08-01 14:10:42
【问题描述】:

我已经用 JSF2.0 和 Richfaces 创建了一个测试项目。我正在尝试绘制图表。现在,我从数据库到 bean 和数据表中获得了价值。现在,当我想将此值传递给 javascript 变量并发现来自 The BalusC 的 answer 非常有用时。它工作正常,但 javascript 变量在 oncomplete="jsonDemo('#{kpilist.json}')" 之后获得的值。即 #{kpilist.json} 的值不是最新的,它是最后一个。

我已经打印了#{kpilist.json} 的值。如果它是在数据表之后打印的,则该值是当前的。如果它在数据表之前打印,则它是最后一个值。自从 a4j:ajax 的 oncomplete 属性在一切完成后执行以来的任何方式,为什么 #{kpilist.json} 不显示最新值? Richfaces和jsf组件的各种listener和oncomplete属性的执行顺序是什么?

我的托管 Bean:

@ManagedBean(name = "kpilist")
@ViewScoped
public class KPIListController implements Serializable {

    private static final long serialVersionUID = 1L;
    boolean state = true;
    String selectedKPIType;
    String selectKPITime = "D";
    boolean renderDatatable;
    String json;



    public String getJson() {
        return json;       
    }


    public boolean isRenderDatatable() {
        return renderDatatable;
    }

    public void setRenderDatatable(boolean renderDatatable) {
        this.renderDatatable = renderDatatable;
    }

    public boolean isState() {
        return state;
    }

    public List<String> showViewList() {
        Logger.getLogger(KPIListController.class.getName()).warning("Show view List:");
        KPIDAO kpiDAO = new KPIDAO();
        try {
            Logger.getLogger(KPIListController.class.getName()).info("Into show view List ---select One");
            return kpiDAO.showViewList(selectKPITime);
        } catch (SQLException ex) {
            ex.printStackTrace();
            Logger.getLogger(KPIListController.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

    public void setState(boolean state) {
        this.state = state;
    }

    public String getSelectedKPIType() {
        return selectedKPIType;
    }

    public void setSelectedKPIType(String selectedKPIType) {
        this.selectedKPIType = selectedKPIType;
    }

    public String getSelectKPITime() {
        return selectKPITime;
    }

    public void setSelectKPITime(String selectKPITime) {
        this.selectKPITime = selectKPITime;
    }

    public List<KPI> getKPI() {
        Logger.getLogger(KPIListController.class.getName()).warning("Get KPI Values:");
        KPIDAO kpiDAO = new KPIDAO();        
         List<KPI> kpiList = new ArrayList<KPI>();

        try {
            kpiList = kpiDAO.getKPI(selectedKPIType);  
            Logger.getLogger(KPIListController.class.getName()).warning("KPI List:"+kpiList.size());            

        } catch (SQLException ex) {
            ex.printStackTrace();
            return null;
        }
         Gson gson = new Gson();
        json= gson.toJson(kpiList);
        return kpiList;
    }

    public void resetFormValues() {       
        Logger.getLogger(KPIListController.class.getName()).warning("Reset form:");
        selectedKPIType = "--";
    }
}

我的观点:

<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:rich="http://richfaces.org/rich" 
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:a4j="http://richfaces.org/a4j"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
    <h:head>

    </h:head>
    <h:body>
        <ui:composition template="/contentTemplate.xhtml">
            <ui:define name="windowTitle">KPI Index</ui:define>
            <ui:define name="content" >

                <h:outputScript name="js/graphics/jquery.js"/>   
                <h:outputStylesheet name="/css/jquery-ui-1.8.22.custom.css"/>
                <h:outputScript name="js/graphics/jquery-ui-1.8.22.custom.min.js"/>
                <h:outputScript name="js/OpenLayers/OpenLayers.js"/>

                <h:outputScript name="js/graphics/raphael-min.js"/>
                <h:outputScript name="js/graphics/canvg.js"/>
                <h:outputScript name="js/graphics/paths.js"/> 
                <h:outputScript name="js/graphics/draw.js"/> 

                <h:form id="ins_sel_form">
                    <h:outputText value="KPI TIME FRAME"/>
                    <h:selectOneRadio value="#{kpilist.selectKPITime}"  >
                        <f:selectItem itemLabel="DAILY" itemValue="D"   />
                        <f:selectItem itemLabel="WEEKLY" itemValue="W"  />
                        <f:selectItem itemLabel="LAST WEEK" itemValue="LW"  />    
                        <a4j:ajax event="change" render="ins_sel_form:selectOnemenu dataPnl"  listener="#{kpilist.resetFormValues()}" /> 
                    </h:selectOneRadio>

                    <h:outputText value="Major KPI Type"/>
                    <h:selectOneMenu id="selectOnemenu" value="#{kpilist.selectedKPIType}"  >
                        <f:selectItem itemValue="--" itemLabel="--"></f:selectItem>
                        <f:selectItems itemValue="#{item.toString()}" var="item" itemLabel="#{item.toString()}" value="#{kpilist.showViewList()}"/>
                        <a4j:ajax event="change" render="dataPnl"  oncomplete="jsonDemo('#{kpilist.json}')" /> 
                    </h:selectOneMenu>

                    <h:outputText value="Show / Hide Map"/>

                </h:form>
                <rich:panel  id ="dataPnl">

                        <rich:dataTable id="kpiValueTable" value="#{kpilist.KPI}" var="kpi" style="width:100%" rows="20" rendered="#{kpilist.selectedKPIType!=null and kpilist.selectedKPIType !='--' }" >                            

                            <rich:column>
                                <f:facet name="header" >
                                    <h:outputText value ="Value"></h:outputText>
                                </f:facet>
                                <h:outputText value="#{kpi.KPIValue}"></h:outputText>
                            </rich:column>

                        </rich:dataTable>
                    JSON String :  <h:outputText  id="json" value ="#{kpilist.json}"/>   
                        <center><rich:dataScroller for="kpiValueTable" rendered="#{kpilist.selectedKPIType!=null and kpilist.selectedKPIType!='--'}"/></center>
                    </rich:panel>

                <rich:panel id="map" style="display: none;">
                </rich:panel>


            </ui:define>
        </ui:composition>
    </h:body>
</html>

Javascript:

function jsonDemo(jsonString){

    console.log("Chart data already retrieved: " + jsonString);
    var data = $.parseJSON(jsonString);    
    $.each(data,function(i,val){
         console.log("The value of i: "+i+" The val: "+val.NCELLCLUSTER);
    });

}

【问题讨论】:

    标签: jsf-2 richfaces page-lifecycle


    【解决方案1】:

    oncomplete 中的 EL 表达式在 JSF 生成 HTML/JS 代码时进行评估(因此,在初始 HTTP 请求中)。正如您所期望的那样,在 JS 中执行 oncomplete 时尚未对其进行评估。评估 EL 表达式的不是网络浏览器,而是网络服务器。 oncomplete 是在render 之后执行的。使用 HTTP 流量调试器和 JS 调试器(在 Chrome/IE9/Firebug 中按 F12),您可以轻松跟踪它。

    有几种解决方法:

    1. 只需在 jQuery 中调用 $.get()$.getJSON() 并在 normal servlet 中完成这项工作,或者更好的是 JAX-RS 网络服务。

      function jsonDemo() {
          $.getJSON("servletURL", function(jsonData) {
              // ...
          });
      }
      
    2. oncomplete 替换为您通过ajax 渲染/更新的&lt;h:outputScript&gt;

      <a4j:ajax ... render="json" />
      ...
      <h:panelGroup id="json">
          <h:outputScript rendered="#{not empty bean.json}">jsonDemo(#{bean.json});</h:outputScript>
      </h:panelGroup>
      

    与具体问题无关,顺便说一句,您在传递 JSON 数据方面存在概念错误。您在传递 jsonDemo('#{kpilist.json}') 这样的参数时对其进行字符串化,然后使用 $.parseJSON() 解析 JSON。这是没有意义的。像 jsonDemo(#{kpilist.json}) 这样删除参数周围的那些单引号,然后你就不再需要 $.parseJSON() 行了。然后数据已经采用 JSON 格式。

    【讨论】:

      【解决方案2】:

      尝试从 a4j:ajax 更改为 f:ajax

      不确定a4j:ajax 是否适用于普通 JSF 组件

      【讨论】:

      • 是的,它可以工作,嗯 .. 但不知道它的组件的执行顺序,如 oncomplete、render 等。
      • 看看这个BalucS的例子,注意onevent="showProgress"showProgress的实现,stackoverflow.com/a/7044332/617373
      猜你喜欢
      • 2012-05-07
      • 1970-01-01
      • 2017-07-18
      • 2013-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-15
      • 2011-06-24
      相关资源
      最近更新 更多