汎用ダイアログボックス

XPagesでダイアログボックスでダイアログボックスを出す方法を紹介した。

今回はダイアログボックスで表示する文言やダイアログ内の[OK]や[CANCEL]を押されたときに走る処理をダイアログの外からコントロールする 方法を紹介しよう。

基本的な考え方

たとえば、最も単純な「保存していいですか?」と確認するダイアログを考えてみよう。 基本こんな感じの設計になる。

  01: <?xml version="1.0" encoding="UTF-8"?>
  02: <xp:view xmlns:xp="http://www.ibm.com/xsp/core">
  03:     <xp:panel id="innerPrompt" >
  04:             <div>
  05:                     <xp:label value="保存していいですか?" />
  06:             </div>
  07:             <div style="margin-top:20px;">
  08:                     <xp:button value="OK" id="button1">
  09:                             <xp:eventHandler event="onclick" submit="true"
  10:                                     refreshMode="complete">
  11:                                     <xp:this.action><![CDATA[#{javascript:
  12:                               document1.save();
  13:                               context.redirectToPage("./view.xsp");
  14:                             }]]></xp:this.action>
  15:                                     <xp:this.script><![CDATA[dijit.byId('ccPrompt').hide()]]></xp:this.script>
  16:                             </xp:eventHandler>
  17:                     </xp:button>
  18:                     <xp:button value="Cancel" id="button2">
  19:                             <xp:eventHandler event="onclick" submit="false">
  20:                                     <xp:this.script><![CDATA[dijit.byId('ccPrompt').hide()]]></xp:this.script>
  21:                             </xp:eventHandler>
  22:                     </xp:button>
  23:             </div>
  24:     </xp:panel>
  

これはこれでいいんだけど、状況に応じて文言を変えたいし、[OK]や[CANCEL]押されたときの処理も変えられないだろうか。 あと、もちろん[OK]押されたときにどの要素を更新すればいいかも状況に応じて異なってくる。

これらの設定を、ダイアログを開く時に指定できると、いろいろ汎用的に使えそう。

文言や処理の指定方法

ダイアログボックスはカスタムコントロールにしてあるから、コンポジット変数として渡してやるという方法がある。 ただ、コンポジット変数は、ダイアログ用のカスタムコントロールを記述するところに書かざるを得ないので、ちょっと不便。できればダイアログを 開くボタンの処理の中に書きたいね。

となると、スコープ変数に記述するのがいいだろう。 たとえば汎用ダイアログ内で参照するスコープ変数が"viewScope.prompt"だったら、viewScope.prompt.message = "保存していいですか?"のように 記述するとか。

ダイアログボックスのコードはこんな感じになる。単にメッセージや事項する処理をviewScope.promptの対応するプロパティに変えただけ。

  01: <?xml version="1.0" encoding="UTF-8"?>
  02: <xp:view xmlns:xp="http://www.ibm.com/xsp/core">
  03:     <xp:panel style="width:99.0%" id="innerPrompt">
  04:       <xp:label value="#{viewScope.prompt.message}"  />
  05:       <div >
  06:         <xp:button value="OK" id="button1">
  07:           <xp:eventHandler event="onclick" submit="true" refreshMode="partial"
  08:             refreshId="#{viewScope.prompt.refreshTarget}">
  09:               <xp:this.action><![CDATA[#{javascript:
  10:                 if (viewScope.prompt.procOK) {
  11:                   viewScope.prompt.procOK();
  12:                 }
  13:               }]]></xp:this.action>
  14:               <xp:this.script><![CDATA[
  15:                 dijit.byId('ccPicklist').hide();
  16:               ]]></xp:this.script>
  17:           </xp:eventHandler>
  18:         </xp:button>
  19:         <xp:button value="Cancel" id="button2" >
  20:           <xp:eventHandler event="onclick" submit="false">
  21:             <xp:this.script><![CDATA[
  22:               dijit.byId('ccPicklist').hide()
  23:             ]]></xp:this.script>
  24:           </xp:eventHandler>
  25:         </xp:button>
  26:       </div>
  28:     </xp:panel>
  29: </xp:view>
  

これを呼び出す側はこんな感じ。結構簡単でしょ。

  01:         <xp:panel id="errorPanel">
  02:           <xp:messages id="messages1"></xp:messages>
  03:         </xp:panel>
  04:
  05:         <div>
  06:           <xp:button id="button3" value="Save"
  07:             rendered="#{javascript:document1.isEditable()}">
  08:             <xp:eventHandler submit="true" event="onclick"
  09:               refreshMode="partial" refreshId="innerPrompt">
  10:               <xp:this.action><![CDATA[#{javascript:
  11:                 viewScope.prompt.message = "保存していいですか?";
  12:                 viewScope.prompt.refreshTarget = "errorPanel";
  13:                 viewScope.prompt.procOK = function() {
  14:                   if ($main.preCheck(document1)) {
  15:                     document1.save();
  16:                     context.redirectToPage("/list.xsp");
  17:                   } else {
  18:                     @ErrorMessage("保存できません", "messages1");
  19:                   }
  20:                 };
  21:               }]]></xp:this.action>
  22:               <xp:this.script><![CDATA[
  23:                 dijit.byId('ccPicklist').show()
  24:               ]]>
  25:               </xp:this.script>
  26:             </xp:eventHandler>
  27:           </xp:button>
  28:         </div>
  

ページをメモリに保存する設定

サンプル

DialogSample.nsfからサンプルをDLできる。 件名がTESTのとき、$main.preCheck()がfalseを返すようになってる。