関連テーブルに新規レコードを作る

INTER-Mediator勉強会2015-#4
June 8, 2015
Masayuki Nii - nii@msyk.net

Agenda

  • Post Onlyモードについて
  • 関連レコードとして新規レコードを追加する
  • いくつかの問題点とその解決方法

入力専用モード(Post Onlyモード)

コンテキストを指定して、新規レコードを作る仕組み

新規レコード作成可能なコンテキストを定義ファイルに記述する
エンクロージャーにdata-im-control="post"という属性を指定
リピーター内にボタンを配置し、data-im-control="post"という属性を指定

その他は通常と同じ

ターゲット指定がコンテキストとフィールドの対応を行う
入力したデータを、新規レコードの初期値として設定する
内部にポップアップメニュー用のエンクロージャー/リピーターがあれば、通常通り展開する

新規レコード作成が必要な場合

このサンプル(Sample_invoice)で、「明細」に新規レコードを作成したい

伝票全体はinvoiceテーブル、明細はitemテーブル(同名のコンテキストを定義)

「追加」ボタンを押せばいいではないか?

repeat-control="confirm-insert"等で、「追加」ボタンは設定できる
現実には、「追加後修正する」という動作を要求する(FileMakerやAccessも実質その動作)
「値を決めてから追加したい」というニーズもあるといえばある

まずはPost Onlyモードのエンクロージャーを追加

<table>
    <tbody data-im-control="post">
    <tr>
        <td><input type="text" data-im="item@product_id" size="2"></td>
        <td><input type="text" data-im="item@qty" size="2"></td>
        <td><button  data-im-control="post">追加</button></td>
    </tr>
    </tbody>
</table>

実際に見てみる

追加はできているのかもしれないけど、明細の行が増えない
invoiceテーブルのidフィールドと、itemテーブルのinvoice_idフィールドが関連レコードの手掛かり
invoice_idフィールドにはPost Onlyモードのエンクロージャー内に、ターゲット指定を持つタグ要素はない

親レコードのidフィールド値が欲しい

idフィールド値は常に変更する

実行時に取得しないといけない
Post Onlyモードで、ボタンを押した後、データベース処理の前後に呼び出すメソッドがある。ここで、処理を追加すれば良い

テキストフィールドから取り出す?

コンテキスト名は固定であり、それを元に、idフィールドが見えているテキストフィールドにたどれば良い
テキストフィールドの値を、新規レコード作成時の初期値のプロパティに設定すれば良い

さらに、画面更新の問題

データベース処理後に、itemコンテキストを再構成すれば良い

これらは、JavaScriptのプログラムで実装できます!

Post Onlyモードでの処理の追加

以下の関数(メソッド)を定義する

INTERMediatorOnPage.processingBeforePostOnlyContext = function(targetNode)  {
    // ボタンを押した直後で、データベース処理の前に実行される
    // trueを返すとデータベース処理に移行する。falseを返すとデータベース処理はせずにキャンセル
};

INTERMediatorOnPage.processingAfterPostOnlyContext = function(targetNode, returnValue) {
    // データベース処理の後に実行される
};

関数を記述する場所

原則どこでもいいが、このサンプルの場合、invoice.jsファイルが用意されているので、そこに記述するのが手軽

invoiceコンテキストのidフィールドの取得

INTERMediatorOnPage.processingBeforePostOnlyContext = function(targetNode)  {

    var mainContext = IMLibContextPool.contextFromName("invoice");
    var nodeId = INTERMediatorOnPage.getNodeIdFromIMDefinitionOnEnclosure("invoice@id", mainContext.enclosureNode);
    var idValue = document.getElementById(nodeId).value;

    INTERMediator.additionalFieldValueOnNewRecord = {};
    INTERMediator.additionalFieldValueOnNewRecord['item'] = {field: "invoice_id", value: idValue};

    return true;
};

APIの説明

IMLibContextPool.contextFromName:
コンテキスト名から、コンテキストのオブジェクトを配列で得る
INTERMediatorOnPage.getNodeIdFromIMDefinitionOnEnclosure:
指定したターゲット指定を持つ要素を、指定したタグ要素の内側で検索し、その要素のid属性値を返す
INTERMediator.additionalFieldValueOnNewRecord:
新規レコードを作成したときの初期値の指定

データベース処理後に画面更新

INTERMediatorOnPage.processingAfterPostOnlyContext = function(targetNode, returnValue) {
    var subContext = IMLibContextPool.contextFromName("item");
    INTERMediator.constructMain(subContext);
};

APIの説明

INTERMediator.constructMain:
引数に指定したコンテキストを再構築する

せっかくなので、ポップアップメニューで商品選択

<table>
    <tbody data-im-control="post">
    <tr>
        <td><select data-im="item@product_id"><option data-im="product@id@value product@name"/></select></td>
        <td><input type="text" data-im="item@qty" size="2"></td>
        <td><button data-im-control="post">追加</button></td>
    </tr>
    </tbody>
</table>

まとめ

  • Post Onlyモードでのカスタマイズの実例
  • INTER-Mediatorは、さまざまなタイミングでメソッド呼び出しを行う
  • クライアントはJavaScript、サーバーサイドはPHPで記述できる