HtmlDataTable のデータ モデルを JSF 2.0 と Facelets で正しく更新するのに問題があります。
HtmlDataTable を拡張し、encodeBegin メソッドで列を動的に追加するカスタム Java ベース コンポーネントを作成しました。
@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() メソッドがユーザー データを使用して一連の文字列を作成します。
フェイスレット ページで宣言された列を含むテスト ケースが正しく機能する (つまり、データ モデルが JSF によって正しく更新される) のはなぜですか?
データ モデルが正しく更新されるようにするために、呼び出す必要があるメソッドまたは拡張する必要があるインターフェイスはありますか?
このテスト ケースを使用して、はるかに複雑なコンポーネントで発生している問題に対処しているため、Facelet 複合コンポーネントを使用して同じ機能を実現することはできません。
これは、NetBeans 6.8、JRE 1.6.0u18、GlassFish 3.0 を使用して行われたことに注意してください。
ご協力いただきありがとうございます。