1

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 を使用して行われたことに注意してください。

ご協力いただきありがとうございます。

4

1 に答える 1

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 );

これは、JSF 2.0 のプログラムによる使用法を示すプロジェクトです。

于 2010-04-19T19:20:11.863 に答える