文書を開くときの処理

文書を開くときの前処理

文書を開くときの前処理を記述したいときは、文書タイプのデータソース定義の部分にpostOpenDocumentとpostNewDocumentの属性に書いたコードが実行される。 既存の文書を開く時がpostNewDOcument、新規に文書を作成するときがpostNewDocument属性に書かれたコードになる。

たいていは、文書OPEN時の処理は長くなるので、ページモジュール内の関数を呼び出すようにしておくといい。複数のXPagesアプリを作る時には関数名は共通化 させておくと、処理を探しやすい。

  01: <?xml version="1.0" encoding="UTF-8"?>
  02: <xp:view xmlns:xp="http://www.ibm.com/xsp/core"
  03:     xmlns:xc="http://www.ibm.com/xsp/custom">
  04:     <xp:this.data>
  05:             <xp:dominoDocument var="document1" formName="main" concurrencyMode="exception">
  06:                     <xp:this.postOpenDocument><![CDATA[#{javascript:$pcBook.postOpenDoc(document1);}]]></xp:this.postOpenDocument>
  07:                     <xp:this.postNewDocument><![CDATA[#{javascript:$pcBook.postNewDoc(document1);}]]></xp:this.postNewDocument>
  08:             </xp:dominoDocument>
  09:     </xp:this.data>
  

文書を短いURLで開く(UNID指定以外の方法で開く)

デフォルトでは、文書を開くURLはこんな感じになる。documentId=xxxxの部分には32文字のUNIDが入るので、結構長いURLになる。

  xxx.nsf/xxx.xsp?documentId=xxxxx...xxxx&action=openDocument
  

これをこんな感じのURLにする方法。

  xxx.nsf/xxx.xsp?ID=KB304525
  

今回も、XPageのデータソースを決める部分に以下のような1行を追加。6行目で$pcBook.calcUNID()を呼んで、文書のUNIDを求めている。

  01:     <xp:this.data>
  02:             <xp:dominoDocument var="document1" formName="main"
  03:                     concurrencyMode="exception" action="openDocument">
  04:                     <xp:this.postOpenDocument><![CDATA[#{javascript:$pcBook.postOpenDoc(document1);}]]></xp:this.postOpenDocument>
  05:                     <xp:this.postNewDocument><![CDATA[#{javascript:$pcBook.postNewDoc(document1);}]]></xp:this.postNewDocument>
  06:                     <xp:this.documentId><![CDATA[#{javascript:$pcBook.calcUNID();]]></xp:this.documentId>
  07:             </xp:dominoDocument>
  08:     </xp:this.data>
  

$pcBook.calcUNID()はこんな感じのコードになってる。URLパラメータからKeyを取得し、主Keyで検索できるビューから文書を求めて、 そのUNIDを返すような処理になってる。ちなみにIDで特定できる文書がなかったり、URLパラメータが指定されてないときはgetUrlParameter()は""を返す。 documentIdの結果が""になると、新規作成扱いになる。エラーページにcontext.redirectToPage()で飛ばしてもいい。

  01:     $pcBook.calcUNID = function() {
  02:       var key = context.getUrlParameter("ID");
  03:       if ((key) && (key.match(/^KB(\d+)/))) {
  04:               // keyは規程とおり
  05:               var view = database.getView("主キー検索用"); // 1列目が主キーでソートされてるビュー
  06:               var doc = view.getDocumentByKey(key);
  07:               if (doc) {
  08:                       // docが見つかったらUNIDを返す
  09:                       return doc.getUniversalID();
  10:               } else {
  11:                       // みつからなかった
  12:                       return ""
  13:               }
  14:       } else {
  15:               // 規定外のID指定
  16:               return ""
  17:       }
  18:     }  
  

ただこのdocumentIdの呼び出しは一度のWebアクセスで全部で4回ほど呼び出されるので注意。なぜかpostOpenDocumentが呼ばれた後でも2回ほど呼ばれる。

この解決方法はKRICKの「IBM Connect 2016 XPAGES 最新動向 Part 3」で解説されている。 以下のように書くのが正解らしい。

  01:      <xp:this.beforePageLoad><![CDATA[#{javascript:
  02:       viewScope.docID=$pcBook.calcUNID();
  03:     }]]></xp:this.beforePageLoad>
  04:     <xp:this.data>
  05:             <xp:dominoDocument var="document1" formName="main"
  06:                     action="openDocument" concurrencyMode="exception"
  07:                     documentId="#{viewScope.docID}">
  08:                     <xp:this.postOpenDocument><![CDATA[#{javascript:$pcBook.postOpenDoc(document1);}]]></xp:this.postOpenDocument>
  09:                     <xp:this.postNewDocument><![CDATA[#{javascript:$pcBook.postNewDoc(document1);}]]></xp:this.postNewDocument>
  10:             </xp:dominoDocument>  
  
  • beforePageLoad内で先にdocumentIDを求めておき、viewScope.docIDに格納(docIDの部分は変数名みたいなものなのでなんでもいい)
  • データソースを決める<xp:dominoDocument>のdocumentId属性にdocumentId="#{viewScope.docID}"を書いておく。"#{javascript:viewScope.docID}"ではないので注意。
  • 要は、beforePageLoadにdocumentIDを求める処理を書いておけば1回しか呼ばれないので、もとめたUNIDをviewScopeに格納しておく
  • "#{viewScope.docID}"の書き方は「式言語(EL)」と呼ばれる記載方法で、関数呼び出しなどはできないが、変数参照などは可能な軽い処理を記述できるというものだろう。 データの格納先の指定用かとも思ってたが、「式言語(EL)」というご大層な名前がついてるんだな。

文書を開くときに編集/表示モードを動的に切り替える

文書を開きときに、状況に応じて編集モードで開いたり、表示モードで開いたりしたいことがある。そのときには、<xp:dominoDocument>のaction属性で指定できる。 ここが"editDocument"なら編集モード、"openDocument"なら表示モードになる。

ここも関数を呼んで、状況に応じて"editDocument"か"openDocument"を返すようにすればいい。

文書と緋づいてないページを開く

要は実体を持たないページをひらくということ。この場合、<xp:dominoDocument>が使えないので、postOpenDocumentイベントが使えない。

こういうときは、ページのbeforePageLoadイベントを使えばいい。ここでviewScopeに必要なデータをつんでおく。後はページ内でviewScopeにつんでおいた データを表示するとか。

例えば、自分宛の文書を集めておいて、表示されるページではxp:repeatなどで一覧表示するなど。

ビュータイプのXPagesを開くときの前処理

ビューを表示する前処理を行いたいときも、ページのbeforePageLoadイベントを使えばいい。ここで前処理を行う自作メソッドを呼べばいい。

ビューのソート指定

呼び出したメソッド中でURLパラメータを取得して、検索キーの指定や表示順の切り替えなどに使用できる。

  $pcBookView.beforePageLoad = function() {
      var key = context.getUrlParameter("key");
      $hc.debug("$pcBookView.beforePageLoad() is called. key=", key);
      viewScope.searchKey = key;  // 後で使う
  }