FormaのスクリプトからAjax処理を呼び出す

このCookBookでは、Formaのスクリプトからサーバサイドロジックを呼び出し、Ajax処理を実現する方法をご紹介します。

  • IM-LogicDesignerを利用し、サーバサイドロジックとその呼び出し口であるREST APIを作成します。
  • FormaのスクリプトからXMLHttpRequestでREST APIを呼び出します。

このCookBookで扱う内容は、IM-FormaDesigner 2015 Winter (8.0.11)以降のバージョンを前提にしています。

完成イメージ

サンプルアプリケーションでは、Ajax処理にて指定したユーザの名称・所属組織を取得して画面に反映しています。


1. ユーザコード・検索基準日への入力を行います。
2. 検索ボタンを押下します。
3. REST APIが呼びだされ、サーバサイドの業務ロジックが実行されます。
4. 取得結果が画面に反映されます。

[iframe width="100%" height="400" src="https://dev-portal.intra-mart.jp/imart/certification?im_user=ueda&im_password=ueda&im_url=/forma/normal/view/regist_application_view/im_cookbook_110542_forma?imui-theme-builder-module=headwithcontainer"]

完成サンプル

以下の完成サンプルをダウンロードしてご活用ください。

ローカル環境で表示させる場合は、テナント環境セットアップ後に以下のURLにアクセスしてください。
http://localhost:8080/imart/forma/normal/view/regist_application_view/im_cookbook_110542_forma
なおベースURLである以下の部分は、環境に合わせて適宜変更してください。
http://localhost:8080/imart

レシピ

  1. サーバサイドロジックを作成する
  2. 作成したサーバサイドロジックをREST APIとして登録する
  3. 登録したREST APIを呼び出すスクリプトを作成する

1. サーバサイドロジックを作成する

 

「IM-LogicDesigner」とは?

IM-LogicDesignerは、Web上でビジネスロジックを簡単に作成することができるアプリケーションです。

「タスク」(処理の部品)を並べ、「ロジックフロー」(フロー図)を作成することで、ビジネスロジックを作成できます。

IMBoxへの投稿・ストレージ操作・メール送信・ジョブの実行などあらかじめ製品から提供されているタスクに加えて、「ユーザ定義タスク」を利用することで開発者がSQLやJavaScriptで独自のタスクを定義することも可能です。

このCookBookでは、ユーザ定義タスク(JavaScript)を利用し、サーバサイドロジックを作成します。

ユーザ定義タスク(JavaScript)の作成

ユーザ定義タスク(JavaScript)の作成方法について簡単にご紹介します。
ユーザ定義タスク(JavaScript)の作成方法の詳細は、「IM-LogicDesigner チュートリアルガイド 5.4.4. ユーザ定義 - JavaScript」を参照してください。

  1. 「サイトマップ」- 「LogicDesigner」-「ユーザ定義一覧」からユーザ定義一覧画面を表示し、「JavaScript定義新規作成」のメニューを押下してください。JavaScript定義編集画面が表示されます。user_task_js
  2. サーバサイドで動作させたい処理(JavaScript)をスクリプト欄に記述してください。記述したJavaScriptは、スクリプト開発モデルのファンクション・コンテナとして実行されます。
    
    /**
     * run.
     *
     * @param input {Object} - task input data.
     * @return {Object} task result.
     */
    function run(input) {
        var result = {};
    
        // 操作ユーザのロケール
        let locale = Contexts.getAccountContext().locale;
    
        // ユーザ検索
        let userManager = new IMMUserManager();
        let userResult = userManager.getUser({'userCd': input.userCd}, input.baseDate, locale);
        if(userResult.error){
            result.error = true;
            result.message = userResult.message;
            return result;
        }else if(userResult.data === null){
            result.error = true;
            result.message = "The user you specified does not exist.";
            return result;
        }
    
        // 所属組織検索
        let immCompanyManager = new IMMCompanyManager();
        let departmentResult = immCompanyManager.listDepartmentWithUser({'userCd': input.userCd}, new AppCmnSearchCondition(), true, input.baseDate, locale) ;
        if(departmentResult.error){
            departmentResult.error = true;
            departmentResult.message = departmentResult.message;
            return result;
        }
        result.data = {};
        result.data.userName = userResult.data.locales[locale].userName;
        result.data.userSearchName  = userResult.data.locales[locale].userSearchName;
        result.data.departmentName = (departmentResult.data.length > 0) ? departmentResult.data[0].displayName : '';
        return result;
    }
    
  3. 画面からスクリプトへ渡す情報を入力値欄に、スクリプトから画面へ返却する情報を返却値欄に設定してください。
  4. ユーザ定義ID・ユーザ定義名・カテゴリ・ソート番号のフィールドに適宜入力を行い、ユーザ定義タスク(JavaScript)を登録してください。
ロジックフロー定義の作成

ロジックフロー定義の作成方法について簡単にご紹介します。
ロジックフロー定義の作成方法の詳細は、「IM-LogicDesigner チュートリアルガイド 4.3. ロジックフロー定義編集画面を開く」を参照してください。

  1. 「サイトマップ」- 「LogicDesigner」-「フロー定義一覧」からロジックフロー定義一覧画面を開き、「新規作成」のメニューを押下してください。ロジックフロー定義編集画面が表示されます。
  2. 以下のタスクを配置してください。
    • 開始タスク
    • 「ユーザ定義タスク(JavaScript)の作成」にて作成したユーザ定義タスク
    • 終了タスク
  3. 各タスク同士の線をつなぎます。
    • 開始タスクのoutとユーザ定義タスクのinをつなげます。
    • ユーザ定義タスクのoutと終了タスクのinをつなげます。

    logic_flow

  4. 入出力設定を行います。
    • 入出力設定のリンクを押下し、入出力設定画面を表示してください。
    • ユーザ定義タスクの設定と同様に、画面からロジックフローへ渡す情報を入力値欄に、ロジックフローから画面へ返却する情報を返却値欄に設定してください。

    input_output

  5. マッピング設定を行います。
    • ユーザ定義タスクを押下し、マッピング設定画面を表示してください。ロジックフローの入力値とユーザ定義タスクの入力値をマッピングしてください。
    • 終了タスクを押下し、マッピング設定画面を表示してください。「入力を追加」のリンクを押下し、ユーザ定義タスクの出力値を追加してください。
    • ユーザ定義タスクの出力値とロジックフローの出力値をマッピングしてください。

    mapping

  6. ロジックフローを保存します。
    • 保存のリンクを押下し、保存設定画面を表示してください。フロー定義名を入力し、作成したロジックフロー定義を保存してください。

2. 作成したサーバサイドロジックをREST APIとして登録する

作成したロジックフロー定義を呼び出すREST APIの登録方法について簡単にご紹介します。
REST APIの登録方法の詳細は、「IM-LogicDesigner チュートリアルガイド 4.12. フロールーティングを設定する」を参照してください。

ロジックフロールーティング設定
  1. 「サイトマップ」- 「LogicDesigner」-「ルーティング定義一覧画面」からフロールーティング定義一覧画面を表示し、「新規作成」のメニューを押下してください。ロジックフロールーティング編集画面が表示されます。routing
  2. 対象フローの検索ボタンを押下し、ロジックフローの一覧を表示してください。作成したロジックフローを選択してください。
  3. 「ルーティング」: REST APIのURLとして利用したい文字列を入力してください。
  4. 「メソッド」: REST APIを呼び出す際のHTTPメソッドの種類を選択してください。
  5. 「認証方法」:「IMAuthentication」を選択してください。
    • IMAuthenticationは、Cookieに含まれるセッションIDを利用して認証を行います。特別な認証処理を行わず、Cookieに紐づくセッションの認証状態でアクセスしてください。
  6. 「認可URI」: REST APIのURLに対する認可リソースに対して設定したいURIを入力してください。
  7. 作成したREST APIを悪用したCSRF攻撃を防ぐために、「セキュアトークンを利用する」を選択してください。
認可設定

登録したREST APIに対する認可設定を行います。

  1. 「サイトマップ」- 「LogicDesigner」-「ルーティング定義一覧画面」からフロールーティング定義一覧画面を表示し、登録したREST APIの「認可」のメニューを押下してください。認可設定画面が表示されます。
  2. REST APIを利用するFormaアプリと同様の権限設定となるように、認可設定を行います。

3. 登録したREST APIを呼び出すスクリプトを作成する

セキュアトークンの埋め込み

IM-FormaDesigner 2015 Winter (8.0.11)をご利用の場合は、以下の手順の実施が必要です。
REST APIの呼び出しに際してセキュアトークンのチェックが行われるため、Formaアプリの画面にセキュアトークンを埋め込みます。

  1. template.htmlをカスタマイズし、imSecureTokenタグを追加してください。template.htmlは、ストレージ上の以下のディレクトリに配置されているFormaアプリの画面のベースとなるHTMLです。
    クライアントタイプ 配置ディレクトリ
    PC版 %Public_Storage%/forma/html_template/template.html
    SP版 %Public_Storage%/forma/html_template/template_sp.html

     

    template.htmlの詳細については、「Formaでのスクリプト開発生産性向上」を参照してください。

  2. template.htmlはメモリ上にキャッシュされているため、更新後にキャッシュをクリアする必要があります。

    テナント管理者としてログインし、「HTMLテンプレートキャッシュ削除」ジョブを実行してください。

スクリプトの作成

登録したREST APIを呼び出すFormaのスクリプトを作成してください。

  1. REST APIへ渡す入力パラメータ・システムパラメータを取得してください。
    • 処理中はインディケータを表示し、ユーザの操作を防ぎます。
    • 日付型のデータは、ISO 8601の拡張形式の文字列で指定してください。
    • リクエストURLのベースとなる部分を取得してください。
    • template.htmlに埋め込んだimSecureTokenタグからセキュアトークンを取得してください。
    
    // クライアントタイプ
    var clientType = forma.funcs.getDisplayClientType();
    
    // 入力パラメータの取得
    var userInfo = {};
    if(clientType === "pc"){
      // インディケータ開始
      $(document.body).imuiIndicator();
      userInfo.userCd = formaItems.product_72_textbox.getItemData.user_cd();
      // ISO 8601の拡張形式指定
      userInfo.baseDate = formaItems.product_72_calendar.getItemData.base_date().toISOString();
    }else{
      // インディケータ開始
      $.mobile.loading('show', window.forma.loaderParam);
      userInfo.userCd = formaItems.product_72_textbox.getItemDataSp({'input_id': 'user_cd'});
      userInfo.baseDate = formaItems.product_72_calendar.getItemDataSp({'input_id': 'base_date'});
    }
    
    // ベースURLの取得
    var baseUrl = jQuery('base').attr('href');
    
    // セキュアトークンの取得
    var secureToken = $('form[name=imfr_csrf_check]').find('input[name=im_secure_token]').val();
    
  2. XMLHttpRequestを利用してREST APIを実行してください。
    • 1で取得したシステムパラメータ・入力パラメータを指定して、REST APIを実行してください。
    
    // REST APIの実行
    $.ajax({
       type: "POST",
       // REST APIのURL
       url: baseUrl + "logic/api/im_cookbook/110542/user_detail_search",
       headers: {
        // セキュアトークン
        'X-Intramart-Secure-Token': secureToken
      },
      async: true,
      dataType: "json",
      // 入力パラメータ
      data: userInfo
    
    }).done(function(response){
        if(clientType === "pc"){
          if(response.error){
            // エラーメッセージの表示
            imuiShowErrorMessage(response.message);
            return;
          }
    
          // ユーザ名の反映
          var args = {};
          args.data = {};
          args.data.user_name = response.data.userName;
          formaItems.product_72_textbox.setItemData.user_name(args);
    
          // フリガナの反映
          args = {};
          args.data = {};
          args.data.furigana = response.data.userSearchName;
          formaItems.product_72_textbox.setItemData.furigana(args);
    
          // 所属組織の反映
          args = {};
          args.data = {};
          args.data.department_name = response.data.departmentName;
          formaItems.product_72_textbox.setItemData.department_name(args);
        }else{
          if(response.error){
            // エラーメッセージの表示
            imspShowErrorMessage(response.message);
            return;
          }
    
          // ユーザ名の反映
          formaItems.product_72_textbox.setItemDataSp({'input_id': 'user_name',
            'inputDataList': {'user_name': response.data.userName}
          });
    
          // フリガナの反映
          formaItems.product_72_textbox.setItemDataSp({'input_id': 'furigana',
            'inputDataList': {'furigana': response.data.userSearchName}
          });
    
          // 所属組織の反映
          formaItems.product_72_textbox.setItemDataSp({'input_id': 'department_name',
            'inputDataList': {'department_name': response.data.departmentName}
          });
        }
    
    }).fail(function(response){
      // セッションタイムアウトエラー画面へ遷移
      if(response.status === 401){
        location.href = baseUrl + "alert/session_timeout_error.jsp";
        return;
      }
      // システムエラー画面へ遷移
      location.href = baseUrl + 'alert/http500.jsp';
    
    }).always(function(data){
      if(clientType === "pc"){
        // インディケータ終了
        $(document.body).imuiIndicator("destroy");
      }else{
        $.mobile.loading('hide', window.forma.loaderParam);
      }
    });