Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

JSFでコンポーネントをプログラムから動的に生成する ~イベント利用~

先日書いた「JSFでコンポーネントをプログラムから動的に生成する」の続きです。

※とある技術調査でやっている実験なので、参考程度でお願いします(^^;

先日のサンプルを改造して、さらに1つ、パネル+プルダウンをプログラムから生成して、片方のプルダウンを選択したイベントで、もう片方のプルダウン内容を変える、ことをやってみました。

言葉だけだとイマイチなので結果の画像を載せると

2つのパネル+プルダウンがそれぞれプログラムから生成されて

f:id:kikutaro777:20130421231440j:plain

片方を選択したイベントで

f:id:kikutaro777:20130421231448j:plain

もう片方のプルダウンの中身が変わる

f:id:kikutaro777:20130421231455j:plain

これだけですが、イベント自体もプログラムで定義しています(^^;
ビューはほとんど定義してなくて、全てプログラムっていう…。

通常、プルダウンのイベントは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を定義したら何か一応できた(^^;けど色々怪しげ。

該当コード抜粋するとこんな感じです。

//Ajaxイベントを生成 EL式でBackingBeanのメソッドを紐づける
AjaxBehavior selectEvent = new AjaxBehavior();
ELContext elCtx = FacesContext.getCurrentInstance().getELContext();
ExpressionFactory expFact = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
String el = "#{hogeBean.changeItems()}";
selectEvent.setUpdate("@form");

//Ajaxイベントをプルダウンに紐付け
codingPullDown2.addClientBehavior("change", selectEvent);
        
//上記のAjaxイベントだけで完結したいが、うまく動かなかったのでValueChangeListener利用
ValueChangeListener changeListener = new MethodExpressionValueChangeListener(expFact.createMethodExpression(elCtx, el,String.class, new Class[]{String.class}));

//ValueChangeListener紐付け        
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にアイテムをセット
    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でビューをほとんど定義せずにプログラムで生成して、さらにイベントも…ってなると、やはり複雑になるので、あまりやりたくないなぁと。。。

にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村