2010-04-19 25 views
0

我在獲取HtmlDataTable的數據模型被JSF 2.0和Facelets正確更新時遇到了問題。JSF 2.0:基於java的自定義組件+ html表格+ facelets =數據模型未更新

我創建了一個自定義的基於Java的組件,它擴展了HtmlDataTable並動態地在encodeBegin方法中添加了列。

@Override 
public void encodeBegin(FacesContext context) throws IOException 
{ 
    if (this.findComponent("c0") == null) 
    { 
    for (int i = 0; i < 3; i++) 
    { 
     HtmlColumn myNewCol = new HtmlColumn(); 
     myNewCol.setId("c" + i); 
     HtmlInputText myNewText = new HtmlInputText(); 
     myNewText.setId("t" + i); 
     myNewText.setValue("#{row[" + i + "]}"); 
     myNewCol.getChildren().add(myNewText); 
     this.getChildren().add(myNewCol); 
    } 
    } 
    super.encodeBegin(context); 
} 

我的測試頁包含以下

<h:form id="fromtb"> 
     <test:MatrixTest id="tb" var="row" value="#{MyManagedBean.model}"> 
     </test:MatrixTest> 
     <h:commandButton id="btn" value="Set" action="#{MyManagedBean.mergeInput}"/> 
    </h:form> 
    <h:outputText id="mergedInput" value="#{MyManagedBean.mergedInput}"/> 

我的管理bean類包含以下

@ManagedBean(name="MyManagedBean") 
@SessionScoped 
public class MyManagedBean 
{ 
private List model = null; 
private String mergedInput = null; 

public MyManagedBean() { 
    model = new ArrayList(); 
    List myFirst = new ArrayList(); 
    myFirst.add(""); 
    myFirst.add(""); 
    myFirst.add(""); 
    model.add(myFirst); 
    List mySecond = new ArrayList(); 
    mySecond.add(""); 
    mySecond.add(""); 
    mySecond.add(""); 
    model.add(mySecond); 
} 

public String mergeInput() 
{ 
    StringBuffer myMergedInput = new StringBuffer(); 
    for (Object object : model) 
    { 
    myMergedInput.append(object); 
    } 
    setMergedInput(myMergedInput.toString()); 
    return null; 
} 

public List getModel() { 
    return model; 
} 

public void setModel(List model) { 
    this.model = model; 
} 

public String getMergedInput() { 
    return mergedInput; 
} 

public void setMergedInput(String mergedInput) { 
    this.mergedInput = mergedInput; 
} 

調用時,頁面被正確地取得3列的表格呈現(在運行時添加)和2行(因爲我的數據模型有2行)。但是,當用戶在輸入字段中輸入一些數據,然後單擊提交按鈕時,模型沒有正確更新,因此mergeInput()方法會創建一系列在同一頁上呈現的空字符串。

我已經在我的自定義組件的decode()方法中添加了一些日誌記錄,我可以看到用戶輸入的參數將與請求一起回傳,但是這些參數並未用於更新數據模型

如果更新我的自定義組件的encodeBegin()方法如下

@Override 
public void encodeBegin(FacesContext context) throws IOException 
{ 
    super.encodeBegin(context); 
} 

,我更新測試頁面如下

<test:MatrixTest id="tb" var="row" value="#{MyManagedBean.model}"> 
     <h:column id="c0"><h:inputText id="t0" value="#{row[0]}"/></h:column> 
     <h:column id="c1"><h:inputText id="t1" value="#{row[1]}"/></h:column> 
     <h:column id="c2"><h:inputText id="t2" value="#{row[2]}"/></h:column> 
    </test:MatrixTest> 

頁面被正確地呈現,這時候用戶輸入數據並提交表單,底層數據模型就會正確更新,mergeInput()方法將用用戶數據創建一系列字符串。

爲什麼在facelet頁面中聲明的列的測試用例工作正常(即數據模型被JSF正確更新),在運行時使用encodeBegin()方法創建列時不會發生同樣的情況?

是否有任何方法需要調用或接口我需要擴展才能確保數據模型正確更新?

我使用這個測試用例來解決出現在更復雜的組件中的問題,因此我無法使用facelet複合組件實現相同的功能。

請注意,這是使用NetBeans 6.8,JRE 1.6.0u18,GlassFish 3.0完成的。

感謝您的幫助。

回答

1

你的問題很可能是在這裏:

myNewText.setValue("#{row[" + i + "]}"); 

你在這裏設置一個字符串值,而不是值綁定。你需要做的是這樣:

Application application = facesContext.getApplication(); 
ExpressionFactory expressionFactory = application 
     .getExpressionFactory(); 
... 
ValueExpression valueExpression = expressionFactory 
      .createValueExpression(facesContext.getELContext(), 
        "#{row[" + i + "]}", String.class); 
myNewText.setValueExpression("value", valueExpression); 

Here's an a project這表明JSF 2.0的程序使用。

+0

嗨,感謝您的建議,但是使用setValueExpression而不是setValue方法並沒有解決問題。在提交表單時,數據模型不會更新。 有沒有其他建議? – mikic 2010-04-20 08:56:42

+0

這是一個複雜的設置,很多事情可能會出錯。我指出的無論如何都是一個問題。嘗試跟蹤/調試,在輸入文本控制渲染器的解碼方法中設置一個斷點並從此處開始跟蹤。 – lexicore 2010-04-20 10:25:30