XPagesでダイアログボックス

XPagesでダイアログボックスを出すサンプルを探していて、いいものを見つけたので紹介する。

XPages技術者コミュニティーのダイアログボックスのサンプルDB(8.5.3 Upgrede Pack 1 使用) というサンプルだ。結構古いので読んだことはあるとは思うのだが。

ボタンを押すと、ダイアログボックスがふわっと表示され、そこで選択した人の名前がボタン横のテキストボックスに入力されるというもの。 ダイアログボックスのサンプル

このサンプルで使われているテクニックはこんな感じ。

あと、ダイアログボックスとは直接は関係ないが、以下のテクニックも参考になる。

※ これまでずっとSSJS(Server Side JavaScript)一筋だったが、いよいよCCJSにも足を踏み入れるときが来たか...

サンプルアプリケーションの構造

サンプルとはかくありたい、という実にシンプルな構成だ。

サンプルコードの解析

xpHome.xsp

メインのページを作っている。

重要なのは、以下の2点。

導入部

では、コードを読んでいこう。XPagesのソースの読み方で紹介しているコードの整形ツールの結果で説明する。

  01: <?xml version='1.0' encoding='UTF-8'?>
  02: <xp:view xmlns:xc="http://www.ibm.com/xsp/custom" dojoParseOnLoad="true" xmlns:xp="http://www.ibm.com/xsp/core" dojoTheme="true">
  03:     <xp:this.resources>
  04:         <xp:script src="/libDialog.js" clientSide="true" />
  05:     </xp:this.resources>
  06:     <script language="Javascript">
  08:               dojo.require("dijit.Dialog");
  09:               XSP.addOnLoad(function(){dialog_create("ccPicklist","Address Book")});
  11:     </script>
  12:     <xp:this.data>
  13:         <xp:dominoDocument var="dominoDocument1" formName="fmMain" />
  14:     </xp:this.data>
  

ダイアログを開くボタン([Address Book]ボタン)

ダイアログを開くボタンである[Address Book]のコードを見てみよう。

  20:  <xp:button id="btnPicklist" value="Address Book">
  21:      <xp:eventHandler submit="false" event="onclick">
  22:          <xp:this.script>
  23:            <![CDATA[
  24:              dijit.byId('ccPicklist').show()
  25:            ]]>
  26:          </xp:this.script>
  27:      </xp:eventHandler>
  28:  </xp:button>
  30:  <xp:td style="width:480px">
  31:      <xp:inputTextarea id="sendTo1" value="#{dominoDocument1.SendTo}" 
              multipleTrim="true" style="height:40px;width:99%" multipleSeparator="," />
  32:  </xp:td>
  

ダイアログを表示する箱の用意

ダイアログを置いておく場所を用意。

  53: <div id="ccPicklist" style="display:none">
  54:    <xc:ccPicklist />
  55: </div>
  

ccPicklist.xsp

ダイアログボックスの設計を決めているカスタムコントロールである。

ダイアログボックス

パネル全体

まずはパネル全体。ごく普通のカスタムコントロール。

  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%">
  途中省略...
  57:     </xp:panel>
  58: </xp:view>
  

OKボタン

OKボタンが押されたら、ビューで選択された名前を取り出し、データソースのSendToを書き換える。

  04: <xp:button id="btnSelect" value="OK" style="width:70px">
  05:     <xp:eventHandler refreshId="sendTo1" refreshMode="partial" submit="true" event="onclick">
  06:         <xp:this.action>
  07:           <![CDATA[
  08:             #{javascript:
  09:               var viewPanel:com.ibm.xsp.component.xp.XspViewPanel = getComponent("viewPanel1");
  10:               var docIDArray = viewPanel.getSelectedIds();  
  11:               var pickData = new Array();
  12:               for( i=0 ; i < docIDArray.length ; i++ ){
  13:                 var docId = docIDArray[i];
  14:                 var doc = database.getDocumentByID(docId);
  15:                 //get value
  16:                 if(doc != null){
  17:                   pickData[i] = doc.getItemValueString("MailAddress")
  18:                 }
  19:               }
  20:               if(pickData != null){
  21:                 //replace value
  22:                 dominoDocument1.replaceItemValue("SendTo", pickData)
  23:               }
  24:             }
  25:           ]]>
  26:         </xp:this.action>
  27:         <xp:this.script>
  28:           <![CDATA[
  29:             dijit.byId('ccPicklist').hide()
  30:           ]]>
  31:         </xp:this.script>
  32:     </xp:eventHandler>
  33: </xp:button>
  

キャンセルボタン

  34: <xp:button id="button1" value="Cancel" style="width:70px">
  35:     <xp:eventHandler submit="false" event="onclick">
  36:         <xp:this.script>
  37:           <![CDATA[
  38:             dijit.byId('ccPicklist').hide()
  39:           ]]>
  40:         </xp:this.script>
  41:     </xp:eventHandler>
  42: </xp:button>
  

ビューパネル

  43: <xp:viewPanel viewStyle="width:99%" id="viewPanel1" rows="30">
  44:     <xp:this.facets>
  45:         <xp:pager id="pager1" partialRefresh="true" xp:key="headerPager" layout="Previous Group Next" />
  46:     </xp:this.facets>
  47:     <xp:this.data>
  48:         <xp:dominoView var="view1" viewName="vwUser" />
  49:     </xp:this.data>
  50:     <xp:viewColumn showCheckbox="true" columnName="FullName" id="viewColumn1">
  51:         <xp:viewColumnHeader id="viewColumnHeader1" value="Name" />
  52:     </xp:viewColumn>
  53:     <xp:viewColumn id="viewColumn2" columnName="$2">
  54:         <xp:viewColumnHeader id="viewColumnHeader2" value="Mail  address" />
  55:     </xp:viewColumn>
  56: </xp:viewPanel>
  

libDialog.js

ダイアログを設定する関数。

  06: function dialog_create(id, title1) {
  07:     var dialogWidget = dijit.byId(id);
  08:     if( dialogWidget ) {
  09:       dialogWidget.destroyRecursive(true);
          }
  10:     dialogWidget = new dijit.Dialog({ title: title1, duration:500},dojo.byId(id));
  11:     
  12:     var dialog = dojo.byId(id);
  13:     dialog.parentNode.removeChild(dialog);
  14:     var form = document.forms[0];
  15:     form.appendChild(dialog);
  16:     
  17:     dialogWidget.startup();
  18: }
  

ダイアログを開くときにSSJSで前処理

今回のサンプルでは、ダイアログを開く前処理を記述してない。ここにSSJSで前処理を記述できればもっと使い道が出てくる。 そのためには、以下のように改造すればいい。

  <xp:button id="btnPicklist" value="Address Book">
      <xp:eventHandler submit="true" event="onclick" refreshMode="partial" refreshId="innerDialog">
          <xp:this.action><![CDATA[#{javascript:
            // ここにSSJSの前処理を記述可能
          }]]></xp:this.action>
          <xp:this.script>
            <![CDATA[
              dijit.byId('ccPicklist').show()
            ]]>
          </xp:this.script>
      </xp:eventHandler>
  </xp:button>
  

これだけで前処理が実装可能になる。

予想だけど、内部ではこんな順序で処理されるんだと思う。

ふーん、よくできてるなぁ。

そのため、ダイアログボックス内を<xp:panel id="innerDialog">で囲っておいてやる。ここで指定している"innerDialog"はダイアログの表示ボタンの 部分更新先に指定したIDと一致させる必要がある。