我有一個非常簡單的表單,它只提交針對同一表單中的組件的ajax請求。在同一頁面(但在表單外),還有一個ui:repeat
,它對從請求作用域託管bean(假設產品類別列表)返回的數組進行迭代。該bean沒有綁定在表單中的屬性,除了ui:repeat
標記的value
屬性之外,沒有以任何其他方式進行訪問。我不明白爲什麼JSF需要在每個ajax回發中重新創建請求範圍的bean,只需就好像我要求將此外部ui:repeat
(與表單無關)與表單中的某個組件一起呈現。ui:在每個ajax請求上評估的重複值表達式
這是一個錯誤?或者它是一種預期的行爲?當然,我可以將bean註釋爲ViewScoped
,但我沒有看到在視圖範圍中存儲類別的原因,因爲它們在回發之間完全是靜態的。
另一種解決方案/解決方法,我發現是呈現ui:repeat
僅在非Ajax請求的情況下:
<ul>
<ui:repeat value="#{someRequestScopedBean.categories}" var="category" rendered="#{not facesContext.partialViewContext.ajaxRequest}">
<li>#{category.name}</li>
</ui:repeat>
</ul>
但我不知道這是否會導致問題,看起來不是很清楚。
測試用例
的index.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h1>Test page</h1>
<p>Random jokes</p>
<ul>
<ui:repeat value="#{oneLiners.list}" var="oneliner">
<li>#{oneliner}</li>
</ui:repeat>
</ul>
<h:form>
<h:selectOneMenu value="#{backingBean.greeting}" hideNoSelectionOption="true">
<f:selectItem value="#{null}" itemLabel="Select a greeting..." noSelectionOption="true"/>
<f:selectItems value="#{backingBean.greetings}"/>
<f:ajax render="@this btn"/>
</h:selectOneMenu>
<h:commandButton id="btn" value="Say Hello!" disabled="#{empty backingBean.greeting}">
<f:ajax render="otxt"/>
</h:commandButton>
<h:outputText id="otxt" value="#{backingBean.greeting}, Maurizio!" style="display: #{empty backingBean.greeting ? 'none' : 'block'}"/>
</h:form>
</h:body>
</html>
請求範圍的bean:
package testuirepajax;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
/**
*
* @author maurizio
*/
@ManagedBean
@RequestScoped
public class OneLiners {
private String[] list;
public OneLiners() {
System.out.println("testuirepajax.OneLiners.<init>()");
list = new String[] {
"Life is wonderful. Without it we'd all be dead.",
"Daddy, why doesn't this magnet pick up this floppy disk?",
"Daddy, what does FORMATTING DRIVE C mean?",
"Never forget: 2 + 2 = 5 for extremely large values of 2.",
"C:\\ is the root of all directories."
};
}
public String[] getList() {
System.out.println("testuirepajax.OneLiners.getList()");
return list;
}
}
形式支持bean:
package testuirepajax;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
/**
*
* @author maurizio
*/
@ManagedBean
@ViewScoped
public class BackingBean {
private String[] greetings;
private String greeting;
public BackingBean() {
System.out.println("testuirepajax.BackingBean.<init>()");
greetings = new String[] {
"Hello", "Hi", "Good morning", "Good evening", "Good night"
};
}
public String[] getGreetings() {
return greetings;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
public String getGreeting() {
return greeting;
}
}
檢查您的容器的輸出。使用似鯖水狼牙魚服務器(船鑽嘴魚科2.2.12),我看行這樣的:
Informazioni: testuirepajax.OneLiners.<init>()
Informazioni: testuirepajax.OneLiners.getList()
Informazioni: testuirepajax.OneLiners.getList()
Informazioni: testuirepajax.OneLiners.getList()
Informazioni: testuirepajax.OneLiners.getList()
Informazioni: testuirepajax.OneLiners.getList()
Informazioni: testuirepajax.OneLiners.<init>()
Informazioni: testuirepajax.OneLiners.getList()
Informazioni: testuirepajax.OneLiners.getList()
Informazioni: testuirepajax.OneLiners.getList()
Informazioni: testuirepajax.OneLiners.getList()
Informazioni: testuirepajax.OneLiners.getList()
從菜單中選擇元素或單擊時「打招呼!」按鈕。
它是否包含輸入組件?哪個JSF impl /版本?類似的錯誤在Mojarra 2.2.7和2.1.29中得到修復。有很好的解決方法!如果有必要的話,可以在未來的讀者加入之前添加'<! - comment - >'。 – BalusC
@BalusC 1)表單中包含一對'h:selectOneMenu'和一個'h:button',但是也出現在包含'h:commandButton'的表單中。 2)Mojarra 2.2.12 – maurizeio
他們在ui裏面:重複?那麼,這種副作用是不可避免的,因爲無論如何JSF需要重申它以便在回發期間恢復這些組件的狀態。 「部分恢復」不幸的是不支持JSF(雞蛋和所有)。 – BalusC