1

質問に対する私の回答wicket での動的 <optgroup> サポートには、スタイリングに WebMarkupContainer および SelectOptions コンポーネントを使用する選択ボックスが含まれていました。

私は実際に、フォームを拡張し、「選択」プロパティを持つBeanをスーパークラスコンストラクターのCompoundPropertyModelとして使用するクラスで、それを使用しようとしています。タイプ MyBean の Bean は、Group2Bean によって表される 1 つの内部グループに属することができ、それらのそれぞれは、Group1Bean によって表される 1 つの外部グループに属することができます。

コード (機密性と DB の取得を非表示にするように変更) は、多かれ少なかれ次のようになります。

Select の HTML コード:

<select wicket:id="select">
    <wicket:container wicket:id="outerRV">
        <optgroup wicket:id="optGroup1">
          <wicket:container wicket:id="rv">
            <optgroup wicket:id="optGroup2">
              <wicket:container wicket:id="selectOptions">
                <option wicket:id="option"></option>
              </wicket:container>
            </optgroup>
          </wicket:container>
        </optgroup>
    </wicket:container>
</select>

フォーム全体の Java コード:

public class MyForm extends Form<FilterBean> {

public MyForm(String id, FilterBean filterBean) {

super(id, new CompoundPropertyModel<FilterBean>(filterBean);

/*
 * ...code to get group1Beans and group2Beans...
 */

/* Select */
Select select = new Select("select");
select.setRequired(true);
add(select);

/* markup repeater for each group1 division */
RepeatingView rvOuter = new RepeatingView("outerRV");
select.add(rvOuter);

for(Group1Bean group1Bean : group1Beans){ /* for each group1 division */

    /* container with unique wicket ID */
    WebMarkupContainer overOptgroup1 = new WebMarkupContainer(rv.newChildId());
    rv.add(overOptgroup1);

    /* outer optgroup, name taken from group1Bean */
    WebMarkupContainer optGroup1 = new WebMarkupContainer("optGroup1");
    overOptGroup.add(optGroup1);
    optGroup1.add(
        new AttributeModifier("label",true,
                              new Model<String>(group1Bean.getName()
        ))
    );

    /* markup repeater for each group2 division */
    RepeatingView rv = new RepeatingView("rv");
    select.add(rv);

    for(Group2Bean group2bean : group2Beans){ /* for each group2 division */

      /* container with unique wicket ID */
      WebMarkupContainer overOptgroup2 =
              new WebMarkupContainer(rv.newChildId());
      rv.add(overOptgroup2);

      /* inner optgroup, name taken from group2Bean and indented */
      WebMarkupContainer optGroup2 = new WebMarkupContainer("optGroup2");
      overOptGroup.add(optGroup2);

      optGroup2.add(new AttributeModifier("style",true,
          new Model<String>("padding-left:15px")));

      optGroup2.add(new AttributeModifier("label",true,
          new Model<String>(group2Bean.getName())));

      /* fetches and displays MyBean options for selected group2 division */
      optGroup2.add(
          new SelectOptions<MyBean>(
              "selectOptions",fetchMyBeansUnder(group2Bean)
              new MyBeanRenderer()
          ).add(new AttributeModifier("style",true,
                   new Model<String>("padding-left="30px")))
      );
    }
}

問題は、モデルの select プロパティが更新されないことです。(デフォルトの) 送信ボタンを押すと、生成された webapp インターフェイスで選択を変更しても、「選択が必要です」というフィードバックが返され、このコンポーネントをリンクしようとしてさらに失敗し、コンポーネントが選択プロパティの値を取得できません。

1.4.6 からジェネリック Select を持つ 1.5.6 にアップデートしようとしましたが、問題は解決しませんでした。Select を拡張していじると、 Select の inputConverter() (送信ボタンが押された後に呼び出される)が option で getDefaultModelObject() を呼び出すときに、選択した SelectOption が null を返す問題に絞り込むことができました。

アイデアはありますか?よろしくお願いします。

4

1 に答える 1

1

わかりました、ばかげた間違いを見つけました。そのコンストラクターを SelectOption に使用すると、モデルはオプションごとに自動的に作成されるのではなく、MyBeanRenderer の getModel() メソッドによって作成されます。Bean 引数から作成されたモデルではなく、空のモデルを返しました。私はそれがレンダラーであるとは思いもしませんでした...それは、その1つのメソッドを次のように変更するだけの問題でした:

public IModel<T> getModel(T bean){
    return new Model<T>(bean);
}

これに何週間も費やしたのに、これを見なかったなんて、いまだに信じられない。

于 2012-05-10T11:24:08.313 に答える