PrimeFacesは非常に便利なコンポーネントが揃っていますが、たまにハマります。
今日ハマったのは、CommandLink(CommandButtonも多分同じですが)とダイアログ周りの動きです。
以前に書いた「PrimeFacesでManaged Bean内の判定結果に応じてダイアログの表示有無を制御をする方法」で、リンクをクリックした場合にManagedBeanの内部状態によって表示ダイアログを切り替える、ことをやりました。
今回もベースとなるシチュエーション(DataTable内のCommandLink)は同じで、やりたい処理は「リンクをクリックしてダイアログが出る場合もあるし、そのままCommandLinkのactionを実行して画面遷移する場合もある」という割と単純なものです。
が、PrimeFacesを触った方はわかると思いますが、CommandButtonやCommandLinkはajax属性がtrue(これがデフォルト)だと画面遷移ができません。これ自体、意外と最初にハマるのですが(^^;
なので、画面遷移する際は
- ajax属性をfalseにして使う
- redirectを使う
のが良いとされています(PrimeFacesのUsers GuideドキュメントのFAQ No.6とか)
今の開発では基本的に前者の方針を取っているのですが、今回やろうとしていることは
「リンクをクリックしてダイアログが出る場合もあるし、そのままCommandLinkのactionを実行して画面遷移する場合もある」
なので
- ダイアログを出すためにはajax=trueじゃないといけない
- 画面遷移するためにはajax=falseじゃないといけない
という矛盾がありました。試しにプログラム内でajaxをtrue/falseとスイッチしたりしましたが駄目でした(^^;
解決方法は「redirectを使う」しかなさそうで以下のような書き方をしました。
JSFのxhtml
<p:commandLink id="lnkEdit" value="編集" ajax="true"
actionListener="#{xxxBean.権限があるのか確認するメソッド(xxxList.xxx)}"
action="#{xxxBean.画面遷移するメソッド()}"
oncomplete="handleEditDialog(xhr, status, args)"/>
<script type="text/javascript">
function handleEditDialog(xhr, status, args) {
if(!args.hasAuth){
accessDlg.show();
}
}
</script>
ManagedBean(CDIの)
public void 権限があるのか確認するメソッド(XXXXX xxx){
boolean hasAuth = false;
RequestContext context = RequestContext.getCurrentInstance();
context.addCallbackParam("hasAuth", hasAuth);
}
public String 画面遷移するメソッド(){
RequestContext context = RequestContext.getCurrentInstance();
Map<String,Object> map = context.getCallbackParams();
boolean auth = (boolean)map.get("hasAuth");
if(!auth){
return null;
}
return "./画面遷移先ページ" + "?faces-redirect=true";
}
上記記述で、明細のリンクをクリックして
ManagedBeanで権限チェック処理とか実行して、権限がなければ以下のようにダイアログ表示して、権限があれば、そのまま編集画面に進む、みたいな挙動が実装できました。
以下のPrimeFaces Community Forumで全く同じことを質問している人がいたため助かりました(^^;
JSF Navigation and AJAX
redirectを普段使わないので、「矛盾してるの、どーやるの!」と地味にハマりました。