Выражение JSF El, сохраняющее старое значение (жизненный цикл JSF)
Я создал тестовый проект с JSF2.0 и richfaces. Я пытаюсь построить график. Теперь я получил значение из базы данных в bean и datatable. Теперь, когда я хотел передать это значение в переменную javascript, я нашел этот ответ от The BalusC очень полезным. Он работает нормально, но значение, которое переменная javascript получает после oncomplete="jsonDemo('#{kpilist.json}')". то есть значение # {kpilist.json} не обновлено, оно является последним.
Я напечатал значение #{kpilist.json}. Если он напечатан после базы данных, значение является текущим. Если он напечатан до даты, это последнее значение. В любом случае, так как атрибут oncomplete a4j:ajax выполняется после того, как все завершено, почему # {kpilist.json} не показывает последнее значение? Каков порядок выполнения различных атрибутов listener и oncomplete для richfaces и компонента jsf?
Мой управляемый боб:
@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);
});
}
2 ответа
EL выражение в вашем oncomplete
оценивается в тот момент, когда код HTML/JS генерируется JSF (таким образом, по первоначальному HTTP-запросу). Это не оценивается в данный момент oncomplete
выполняется в JS, как вы, кажется, ожидаете. Это не веб-браузер, который оценивает выражения EL, это веб-сервер. oncomplete
кстати только что казнили после render
, С помощью отладчика HTTP-трафика и JS-отладчика (нажмите F12 в Chrome/IE9/Firebug) вы можете легко отследить его.
Есть несколько возможностей решить эту проблему:
Просто вызвать
$.get()
или же$.getJSON()
в jQuery и выполняйте работу в обычном сервлете, а лучше - в веб-сервисе JAX-RS.function jsonDemo() { $.getJSON("servletURL", function(jsonData) { // ... }); }
Заменить
oncomplete
некоторыми<h:outputScript>
который вы рендеринг / обновление с помощью ajax.<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}')
а затем вы анализируете JSON впоследствии, используя $.parseJSON()
, Это не имеет никакого смысла. Удалить эти одинарные кавычки вокруг аргумента, как это jsonDemo(#{kpilist.json})
и тогда тебе это не нужно $.parseJSON()
линия больше. Данные тогда уже в формате JSON.
Попробуйте изменить с a4j:ajax
в f:ajax
не уверен если a4j:ajax
работает с простыми компонентами JSF