先日書いた「JSFでコンポーネントをプログラムから動的に生成する」の続きです。
※とある技術調査でやっている実験なので、参考程度でお願いします(^^;
先日のサンプルを改造して、さらに1つ、パネル+プルダウンをプログラムから生成して、片方のプルダウンを選択したイベントで、もう片方のプルダウン内容を変える、ことをやってみました。
言葉だけだとイマイチなので結果の画像を載せると
2つのパネル+プルダウンがそれぞれプログラムから生成されて
片方を選択したイベントで
もう片方のプルダウンの中身が変わる
これだけですが、イベント自体もプログラムで定義しています(^^;
ビューはほとんど定義してなくて、全てプログラムっていう…。
通常、プルダウンのイベントはPrimeFacesを利用している場合
<p:selectOneMenu >
<p:ajax event="change" listener="#{hogeBean.hogeMethod}" update="@form" />
<f:selectItems value="#{hogeBean.hogeList" />
</p:selectOneMenu>
のように書きます(ajaxタグを利用しない場合はselectOneMenuのvalueChangeListenerを利用)
これをプログラムで書くとどうなるんだ…と調べてみたところ、結構やろうとする人がいるのか、情報はそこそこにありました。
で、AjaxBehaviorを使えば良さそうとわかったのですが、実際には上手く動きませんでした(-_-;なんかPrimeFacesのForumとかStackOverflowでもチラホラ「動かない」といってる人がいたけど、珍しく良い回答がなかったです。
で、試行錯誤してたら、ValueChangeListenerなら動きました。ただSelectOneMenuにはupdate属性が存在しないため、そこはAjaxBehaviorを定義したら何か一応できた(^^;けど色々怪しげ。
該当コード抜粋するとこんな感じです。
AjaxBehavior selectEvent = new AjaxBehavior();
ELContext elCtx = FacesContext.getCurrentInstance().getELContext();
ExpressionFactory expFact = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
String el = "#{hogeBean.changeItems()}";
selectEvent.setUpdate("@form");
codingPullDown2.addClientBehavior("change", selectEvent);
ValueChangeListener changeListener = new MethodExpressionValueChangeListener(expFact.createMethodExpression(elCtx, el,String.class, new Class[]{String.class}));
codingPullDown2.addValueChangeListener(changeListener);
で、Backing BeanにchangeItems()を定義して、中身を入れ替える処理をとりあえずベタに書きます。
public void changeItems(){
List<SelectItem> newItems = new ArrayList<>();
newItems.add(new SelectItem("newKey1", "イベントで入れ替わった項目1"));
newItems.add(new SelectItem("newKey2", "イベントで入れ替わった項目2"));
newItems.add(new SelectItem("newKey3", "イベントで入れ替わった項目3"));
UISelectItems selectItems = new UISelectItems();
selectItems.setValue(newItems);
SelectOneMenu codingPullDown = (SelectOneMenu)FacesContext.getCurrentInstance().getViewRoot().findComponent(":frmDg:pdmCoding");
List<UIComponent> removeList = codingPullDown.getChildren();
codingPullDown.getChildren().removeAll(removeList);
codingPullDown.getChildren().add(selectItems);
}
技術調査とはいえ、JSFでビューをほとんど定義せずにプログラムで生成して、さらにイベントも…ってなると、やはり複雑になるので、あまりやりたくないなぁと。。。