Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AngularJSとバックエンドサービスAppPotで作る業務システム入門(Short Ver.)

AppPot
November 18, 2016

AngularJSとバックエンドサービスAppPotで作る業務システム入門(Short Ver.)

AppPot

November 18, 2016
Tweet

More Decks by AppPot

Other Decks in Technology

Transcript

  1. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 内容 所要時間 AppPotの概要説明 10分 演習内容の説明 + 演習の準備 10分 Exercise 0 アプリの登録 5分 Exercise 1 データベースの⽣成機能の実装 10分 Exercise 2 登録機能の実装 15分 Exercise 3 検索機能の実装 10分 ハンズオンのタイムテーブル
  2. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 特徴③ 特徴② AppPotとは 企業のスマートデバイス活⽤を⽀援する モバイルアプリの開発/運⽤プラットフォームです 既存の社内システムとの 連携が容易 サーバー開発不要 企業で必要な機能を 実装済み 特徴① ίετ࡟ݮº։ൃظؒ୹ॖ
  3. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 企業のスマートデバイス活⽤における課題 n  アプリを多数作成したいが、コストがかかってしまう ü  アプリごとにサーバーを構築・運⽤している ü  アプリごとに同じような機能を重複して開発している n  アプリ開発のスピードが業務ニーズに追いついていない ü  アプリ以外にもサーバーの構築、開発が必要 n  タブレットを導⼊したが、カタログなど ごく⼀部に活⽤範囲が制限されている ü  業務で使⽤するデータのセキュリティ確保や、 既存システムとの連携の⼿法が確⽴されていない
  4. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. AppPotの導⼊効果 サーバー開発が不要でモバイルアプリの導⼊のリードタイム、コスト削減 ユーザー 部門 IT部門 モバイルアプリ エンジニア サーバーアプリ エンジニア インフラ エンジニア アプリ作成依頼 作業依頼 データセンター を借りなきゃ! セキュリティの設計は 時間がかかる。 どうやって基幹システ ムに接続するか 画⾯は早くできたん だけど・・・ 2ヶ⽉以内に マーケティング⽤ のアプリが必要! 2ヶ⽉は 無理です ユーザー部門 IT部門 モバイルアプリ エンジニア アプリ作成依頼 作業依頼 画⾯だけの開発 であれば、すぐ できます 2ヶ⽉以内に マーケティング⽤の アプリが必要! OKです 従来型のアプリ開発 AppPotを使⽤したアプリ開発
  5. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. AppPotが提供する主な機能 ①  グループ、ユーザー及びアプリの権限管理 ②  ログイン/ログアウトなどの認証 LDAP / Active Directory / Google Apps連携も可能 ③  端末とサーバー間のデータの同期 ④  アプリの使⽤状況、エラーの情報収集 ⑤  端末内のデータの暗号化 ⑥  プッシュメッセージの送受信 ⑦  Eメールの送受信 ⑧  バイナリファイルAPI ⑨  他システムとの連携(データベース、Webサービス他)
  6. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. クラウド AppPotの概要アーキテクチャ AppPotサーバー Systems 既存システム群 Systems 他システム データ コネク ター         認証・認可 データ管理 プッシュ メッセージ ロギング 管理コンソール データベース、 Webサービス等 アプリ配布 デバイス管理 AppPot DB Client Application SDK Client Application SDK Client Application SDK Client Application AppPot SDK AppPot機能 提供範囲 AppPot機能 提供範囲外 スマートフォン/タブレット システム連 携 システム連携 API MDM 凡例 ユーザー管理 アプリ管理
  7. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 企業向けに特化したバックエンドサービス 企業システムとの連携 ActiveDirectoryや Googleアカウントとの 認証の連携、既存のDB やWebサービスなど他 システム連携など企業 システムで必要な機能 が⽤意されている DBはNoSQLではなく あえてRDBMSを採⽤ 複雑なJoinなど業務シ ステムのデータを扱う のに⼗分な機能がある クラウドでもオンプレ ミスでも企業のポリ シーに合わせて選択可 能 オンプレミスからクラ ウドへの移⾏も可能
  8. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. ハンズオンアプリの仕様 n  処理概要 •  AppPotサーバー内に⽣成されたローカルDBのテーブルにアクセスし、データの登 録と検索を⾏う n  接続先テーブルのレイアウト •  customer(顧客テーブル) 項⽬名 型 説明 customerId String 顧客ID name String 顧客名 zip String 郵便番号 address String 住所 phone String 電話番号 sex Number 性別(0:男性、1:⼥性)
  9. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. ハンズオンアプリの仕様(画⾯) ①検索条件を⼊⼒ ②検索ボタンを押下すると  検索結果を表⽰ ③新規登録ボタンを押下すると  データ⼊⼒画⾯がダイアログ表⽰ ④保存ボタンを押下すると  ⼊⼒したデータをDBに登録してダイアログを閉じる ⑤キャンセルボタンを押下すると  ⼊⼒したデータを破棄してダイアログを閉じる
  10. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 開発環境の準備 n  node.jsとnpmのインストール •  ダウンロードページ https://nodejs.org/en/download/ n  node.jsのhttp-serverのインストール •  インストールコマンド $ npm install –g http-server •  起動コマンド ドキュメントルートディレクトリに移動 $ http-server
  11. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. ハンズオンコードのダウンロード n  GitHubでハンズオンのコードを公開中 •  https://github.com/NCDCHub/AppPot-AngularJS-HandsOn-ShortVer •  ダウンロード⽅法 •  gitでcloneする •  GitHubのreleaseからzipファイルをダウンロードし、任意のディレクトリ に展開 release > v1.0.0 > Source code (zip)
  12. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 動作確認 n  http-serverの実⾏ $ cd (配置場所)/AppPot-AngularJS-HandsOn-ShortVer/work/www $ http-server この様な画⾯が 表⽰される
  13. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. ハンズオンアプリコード全体像の説明 AppPot-AngularJS-HandsOn-ShortVer ├── exercise01 ... エクササイズ1の解答コード ├── exercise02 ... エクササイズ2の解答コード ├── exercise03 ... エクササイズ3の解答コード └── work ... 今回のハンズオンで作業してもらうディレクトリ   └── www ... Webサーバーのドキュメントルート ├── components ... 実装モジュールを配置するルート │ ├── app.js ... AngularJSのエントリポイント │ ├── auth ... 認証機能のモジュールを配置 │ │ ├── login.css ... ログイン画面用のCSS │ │ ├── login.html ... ログイン画面 │ │ └── LoginController.js ... ログイン関連処理を実装したController │ ├── config.js ... AppPot接続とSDK利用のための設定 │ ├── helper.js ... 軽微な処理用のヘルパー関数郡 │ └── customer ... Customerテーブルにアクセスする機能のモジュールを配置 │ ├── customerDetail.html ... 登録・編集画面 │ └── customerList.html ... 一覧表示画面 ├── index.html ... アクセスするルートページ └── lib ... 外部ライブラリを配置 ├── angular ... AngularJSに関するライブラリを配置 ├── apppot ... AppPotに関するライブラリを配置 ├── bootstrap ... Bootstrapに関するライブラリを配置 └── ui-bootstrap ... AngularJSにBootstrapを組み込むためのライブラリを配置
  14. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. コラム① AngularJSとは View Controller Model Template (HTML) Directive (ngBind/etc…) Controller Service ($xxx/etc…) Scope ビジネス ロジック 「データ」と「振る舞い」を 双⽅向にバインディング 利⽤ DI n  SPA向けのクライアントサイドJavaScript MVCフレームワーク •  MとVとCの依存関係を切り離し、ロジックの配置先を適切に整理する事が可能 •  画⾯とデータを双⽅向にバインドして、それぞれの変更を⾃動的に反映する事が可能 UIとビジネスロジック を紐付ける処理
  15. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. EXERCISE 0 アプリの登録
  16. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 演習内容 n  AppPotの管理コンソールから作成するアプリの登録を⾏な う 管理者IDでログイン アプリの情報を⼊⼒ アプリを登録
  17. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 配布した管理者アカウントでログイン http://trial.apppot.net/apppot/
  18. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. アプリ定義の作成 アプリ管理を選択 追加をクリック
  19. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. アプリの情報を⼊⼒ 任意の名前 任意のID 今回は後でDBを識別す るためログイン時に使 ⽤したユーザー名と ⼀緒にする バージョンの識別⼦ 任意の値 今回は60を指定 今回はMONITOR を指定 今回は開発を選択 開発と本番でログやPush通 知の環境などが切り替わる アプリにアクセスできるグループを指 定 開発⽤に組み込みで⽤意されてい る””グループを指定 アプリID、アプリ バージョン、アプリ キーは後ほどコード 実装時に利⽤するの でコピーしておく
  20. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. EXERCISE 1 データベースの⽣成機能の実装
  21. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 完成イメージ demo⽤のIDとPWでログ インし、検索画⾯を表⽰ するタイミングで Customerテーブルを⽣成 する demo⽤のIDとPW  ID: demo  PW: changeit
  22. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. AppPotへの接続設定 angular.module("app") .value("AppPot", AppPotSDK.getService({ url: "http://trial.apppot.net/apppot/", appId: "XXXXXXXXXXXXXXXX", appKey: "XXXXXXXXXXXXXXXXXX", appVersion: "XXXXX", companyId: XX })); components/config.js 割り当てられたテ ナントのIDを指定 作成したアプリ のキーを指定 作成したアプ リのIDを指定 作成したアプリの バージョンを指定 AppPotのURL
  23. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. モデル(Customer)の定義 angular.module("app") .factory("Customer", ["AppPot", function(AppPot) { var customer = AppPot.defineModel("customer", { "customerId": { type: AppPot.DataType.Varchar }, "name": { type: AppPot.DataType.Varchar }, "zip": { type: AppPot.DataType.Varchar }, "address": { type: AppPot.DataType.Varchar }, "phone": { type: AppPot.DataType.Varchar }, "sex": { type: AppPot.DataType.Long } }); return customer; }]); components/customer/Customer.js • モデルのスキーマを定義 • この定義を元にAppPotがDB にテーブルを⾃動⽣成する • Varcharは⽂字列型、Longは 整数型 Customer.jsファイルを作成し、Customerテー ブル操作⽤のデータモデルとして実装
  24. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. データベース⽣成処理の追加 angular.module("app") .controller("CustomerController",   ["Customer", "AppPot", function(Customer, AppPot) { AppPot.createDatabase([Customer]) .catch(error => { notifyError(error); }); }]); components/customer/CustomerController.js Customerモデル をとAppPot SDK を参照に追加 Customerモデルに定義し たスキーマでAppPot上に データベースを⽣成する 処理 データベースを⽣成するAPI呼び出し AppPotのサーバーAPI呼び出しは基本 的にPromise形式となる CustomerController.jsファイルを作成し、 Customerテーブル⽣成処理を実装 エラーが発⽣した場合に、コンソー ルと画⾯にエラーを通知するヘル パー関数を利⽤
  25. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. コラム② Promiseとは n  ⾮同期処理によるコールバック地獄を解消するためのデザインパターン n  連続する⾮同期処理をあたかもシーケルシャルな処理のように記述できる n  順序付けしたい⾮同期処理間の依存関係を切り離せる // A→B→Cの順番で処理したい function asyncA() { 非同期処理A } function asyncB() { 非同期処理B } asyncA(); asyncB(); 処理C // 従来のやり方 function asyncA(callbackB, callbackC) { 非同期処理A callbackB(callbackC); } function asyncB(callbackC) { 非同期処理B callbackC(); } asyncA(asyncB, function() { console.log('C'); }); // Promiseを使った場合 function asyncA() { return new Promise(function(resolve) { 非同期処理A resolve(); }); }; function asyncB() { return new Promise(function(resolve) { 非同期処理B resolve(); }); }; asyncA() .then(asyncB) .then(function() { console.log('C'); }); •  ⾮同期処理の呼び出しに順 序関係がある •  実際はこのコードのように は実装できない •  通常はコールバックを使って順⼥性を担保する •  コールバックは数が増えるとネストが深くなり処 理がわかりにくい •  ⾮同期処理間に依存関係が⽣まれ再利⽤が難しい •  ⾮同期処理を同期処理に近い⾒た⽬で記述でき、 わかりやすい •  Promiseというプロトコルを介す事で⾮同期関数 間の依存関係がなくなり、再利⽤し易い
  26. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 画⾯とCustomerControllerの紐付け angular.module("app", ["ngRoute", "ui.bootstrap"]) .config(["$routeProvider", function($routeProvider) { $routeProvider .when("/login", { controller: "LoginController", controllerAs : "$ctrl", templateUrl: "components/auth/login.html?v=" + new Date().getTime() }) .when("/customer", { controller: "CustomerController", controllerAs : "$ctrl", templateUrl: "components/customer/customerList.html?v=" + new Date().getTime() }) .otherwise({ redirectTo: "/customer" }); }]) components/app.js customerList.htmlにCustomerControllerを 紐付ける controllerAs構⽂を利⽤して""$ctrl"という名 前を付ける app.jsのrouteProviderにて、 /customerにアクセスした際に表⽰される customerList.htmlを制御するコントローラとし てCustomerControllerを指定する
  27. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. CustomerとCustomerControllerを参照パスに追加 <head> … <link rel="stylesheet" href="lib/bootstrap/css/bootstrap.css"> <link rel="stylesheet" href="components/auth/login.css"> <script type="text/javascript" src="lib/angular/angular.js"></script> <script type="text/javascript" src="lib/angular/angular-route.js"></script> <script type="text/javascript" src="lib/apppot/apppot.js"></script> <script type="text/javascript" src="lib/ui-bootstrap/ui-bootstrap-tpls-0.13.3.js"></script> <script type="text/javascript" src="components/app.js"></script> <script type="text/javascript" src="components/config.js"></script> <script type="text/javascript" src="components/helper.js"></script> <script type="text/javascript" src="components/auth/LoginController.js"></script> <script type="text/javascript" src="components/NavigationController.js"></script> <script type="text/javascript" src="components/customer/Customer.js"></script> <script type="text/javascript" src="components/customer/CustomerController.js"></script> </head> index.html パスの追加
  28. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. ⽣成されたデータベースの確認 n  phpMyAdminにアクセスしてCustomerテーブルが⽣成さ れているか確認 •  URLとアカウントは配布されている資料を確認してください
  29. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. ⽣成されるテーブルのレイアウト n  テーブル名 •  customer(顧客テーブル) n  レイアウト 項⽬名 型 説明 objectId String サロゲートキー。AppPot組込項⽬。AppPotが⾃動更新。 customerId String 顧客ID name String 顧客名 zip String 郵便番号 address String 住所 phone String 電話番号 sex Number 性別(0:男性、1:⼥性) scopeType Number データの参照範囲。AppPot組込項⽬。 createTime Number クライアントでのデータ⽣成時間。UNIXTIME形式。AppPot組込項⽬。 updateTime Number クライアントでのデータ更新時間。UNIXTIME形式。AppPot組込項⽬。 createUserId Number データ⽣成ユーザID。AppPot組込項⽬。AppPotが⾃動更新。 groupIds String データ⽣成/更新したユーザの所属グループID。AppPot組込項⽬。AppPotが⾃動更新。 serverCreateTime String サーバで記録されるデータ作成⽇時。AppPot組込項⽬。AppPotが⾃動更新。 serverUpdateTime String サーバで記録されるデータ更新⽇時。AppPot組込項⽬。AppPotが⾃動更新。 serverRecordStatus Number レコードの状態。AppPot組込項⽬。AppPotが⾃動更新。
  30. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. EXERCISE 2 登録機能の実装
  31. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 完成イメージ 新規作成ボタンを押下す るとデータ⼊⼒ダイアロ グがポップアップする 値を⼊⼒し保存ボタンを 押下するとデータをDBに 保存し⼀覧画⾯に戻る 登録をキャンセルして ダイアログを閉じる
  32. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 新規登録ダイアログ表⽰の実装 angular.module("app") .controller("CustomerController", ["$scope", "$modal", "Customer", "AppPot", function($scope, $modal, Customer, AppPot) {
 AppPot.createDatabase([Customer]) .catch(error => { notifyError(error); }); this.detailDialog = null; this.showDialog = function() { this.customer = new Customer(); this.detailDialog = $modal.open({ templateUrl: "components/customer/customerDetail.html?v=" + new Date().getTime(), backdrop: "static", scope: $scope }); }; }]); components/customer/CustomerController.js モーダルダイアログを利⽤するた めのリソースを参照に追加 customerDetail.htmlを 画⾯テンプレートとし て、新規登録⽤のモー ダルダイアログを開く モーダルダイアログ内で表⽰する Customerオブジェクトをバインドする 変数に、新規Customerインスタンスを 設定 ダイアログの状態を保持す る変数を定義 開発中はAngularJSのテンプレートのキャッ シュを無効化するため、キャッシュのキーと なるURLに常に可変な値を付加する
  33. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 新規登録ボタンにダイアログを紐付ける <table class="table table-striped"> <caption> <input type="button" class="btn btn-primary btn-sm pull-right" x-ng-click="$ctrl.showDialog()" value="新規作成" /> </caption> <thead> <tr> <th>顧客ID</th> <th>顧客名</th> ... </tr> </thead> <tbody> <tr> <td></td> <td></td> ... </tr> </tbody> </table> components/customer/customerList.html 新規作成ボタン押下時に CustomerContollerの showNewDialog関数を呼び出す
  34. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 登録処理とキャンセル処理を実装 angular.module("app") .controller("CustomerController", ["$scope", "$modal", "Customer", "AppPot", function($scope, $modal, Customer, AppPot){ ... this.saveAndCloseDialog = function() { this.customer.insert() .then(() => { this.detailDialog.close(); this.detailDialog = null; this.customer = null; }) .catch(error => { notifyError(error); }); }; this.dismissDialog = function() { this.detailDialog.dismiss(); this.detailDialog = null; this.customer = null; }; }]); components/customer/CustomerController.js 登録処理を実⾏してダイ アログを閉じる 登録をキャンセルしてダ イアログを閉じる ダイアログにバインドされている Customerオブジェクトの内容を元 にデータ登録するAPIを呼び出す。 データ登録APIはPromise形式
  35. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 登録処理と画⾯を紐付ける① <div class="panel panel-primary" style="margin-bottom: 0px"> <div class="panel-heading"> <h3 class="panel-title text-center">顧客登録</h3> </div> <div class="panel-body"> <form name="customerForm" novalidate> <div class="form-group"> <label class="control-label" for="objectId">オブジェクトID</label> <input type="text" class="form-control" name="objectId" x-ng-readonly="true" x-ng-model="$ctrl.customer.objectId"/> </div> <div x-ng-class="{'form-group': true, 'has-error': customerForm.customerId.$dirty && customerForm.customerId.$invalid}"> <label class="control-label" for="customerId">顧客ID</label> <input type="text" class="form-control" name="customerId" x-ng-model="$ctrl.customer.customerId" x-ng-required="true" /> ... </div> <div x-ng-class="{'form-group': true, 'has-error': customerForm.name.$dirty && customerForm.name.$invalid}"> <label class="control-label" for="name">顧客名</label> <input type="text" class="form-control" name="name" x-ng-model="$ctrl.customer.name" x-ng-required="true"/> ... </div> <div x-ng-class="{'form-group': true, 'has-error': customerForm.zip.$dirty && customerForm.zip.$invalid}"> <label class="control-label" for="zip">郵便番号</label> <input type="text" class="form-control" name="zip" x-ng-model="$ctrl.customer.zip"/> </div> <div x-ng-class="{'form-group': true, 'has-error': customerForm.address.$dirty && customerForm.address.$invalid}"> <label class="control-label" for="address">住所</label> <input type="text" class="form-control" name="address" x-ng-model="$ctrl.customer.address" /> </div> <div x-ng-class="{'form-group': true, 'has-error': customerForm.phone.$dirty && customerForm.phone.$invalid}"> <label class="control-label" for="phone">電話番号</label> <input type="text" class="form-control" name="phone" x-ng-model="$ctrl.customer.phone" x-ng-required="true" x-ng-pattern="/^[0-9]+$/" /> ... </div> ... </form> ... </div> ... </div> components/customer/customerDetail.html CustomerContollerで定 義した詳細画⾯⽤の Customer変数の各種プ ロパティを⼊⼒フィール ドにバインドする
  36. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 登録処理と画⾯を紐付ける② <div class="panel panel-primary" style="margin-bottom: 0px"> ... <div class="panel-body"> <form name="customerForm" novalidate> ... <div x-ng-class="{'form-group': true, 'has-error': customerForm.sex.$dirty && customerForm.sex.$invalid}"> <label class="control-label" for="sex">性別</label> <input type="text" class="form-control" name="sex" x-ng-model="$ctrl.customer.sex" x-ng-required="true" x-ng-pattern="/^[0-1]+$/"/> ... </div> <div class="form-group"> <label class="control-label" for="serverCreateTime">登録日</label> <input type="text" class="form-control" name="serverCreateTime" x-ng-readonly="true" x-ng-model="$ctrl.customer.serverCreateTime" /> </div> <div class="form-group"> <label class="control-label" for="serverUpdateTime">更新日</label> <input type="text" class="form-control" name="serverUpdateTime" x-ng-readonly="true" x-ng-model="$ctrl.customer.serverUpdateTime" /> </div> </form> </div> <div class="panel-footer container-fluid" style="padding-left: 0px; padding-right: 0px"> <div class="row-fluid">   <div class="col-md-offset-3 col-md-6"> <input type="button" class="btn btn-primary" style="width: 48%" x-ng-click="$ctrl.dismissDialog()" value="キャンセル" /> <input type="button" class="btn btn-primary pull-right" style="width: 48%" x-ng-disabled="customerForm.$invalid" x-ng-click="$ctrl.saveAndCloseDialog()" value="保存" /> </div> </div> </div> </div> components/customer/customerDetail.html CustomerContollerで定 義した詳細画⾯⽤の Customer変数の各種プ ロパティを⼊⼒フィール ドにバインドする キャンセルボタンが押下され た時にCustomerContollerの dismissDialog関数を呼びだす 保存ボタンが押下された時 にCustomerContollerの saveAndCloseDialog関数 を呼びだす
  37. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. EXERCISE 3 検索機能の実装
  38. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 完成イメージ 検索条件を⼊⼒し、検 索ボタンを押下すると 検索結果が表⽰される
  39. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 検索処理の実装 angular.module("app") .controller("CustomerController", ["$scope", "$modal", "Customer", "AppPot", function($scope, $modal, Customer, AppPot) { … this.condition = {} this.findList = function() { let customerId = nullToBlank(this.condition.customerId); let name = nullToBlank(this.condition.name); Customer.select() .where("#customer.customerId like ? AND #customer.name like ?" , "%" + customerId + "%", "%" + name + "%") .orderBy("#customer.customerId", AppPot.Model.Order.asc) .findList() .then(result => { this.customers = result.customer; $scope.$apply(); }) .catch(error => { notifyError(error); }); }; … }]); components/customer/CustomerController.js ⼊⼒がされなかった場合 は空⽂字に変換 nullToBlankはhelper関数 画⾯の検索条件⼊⼒フィールドと バインドする変数 • 指定したクエリでデータアク セスを実⾏するAPI呼び出し • Customerテーブルに対して SELECTを実⾏ 検索結果を画⾯のテーブルにバイ ンドするcustomers変数に代⼊ ⾮同期実⾏中の変更を画 ⾯に反映
  40. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 検索処理と画⾯を紐付ける① <div class="container"> <div class="panel panel-primary"> <div class="panel-heading"> <h3 class="panel-title text-center">顧客検索</h3> </div> <div class="panel-body"> <div class="form-horizontal"> <div class="form-group"> <div class="col-md-2"><label class="control-label pull-right">顧客ID</label></div> <div class="col-md-3"> <input type="text" class="form-control" x-ng-model="$ctrl.condition.customerId"/> </div> </div> <div class="form-group" style="margin-bottom: 0px"> <div class="col-md-2"><label class="control-label pull-right">顧客名</label></div> <div class="col-md-3"> <input type="text" class="form-control" x-ng-model="$ctrl.condition.name" /> </div> <div class="col-md-offset-4 col-md-3"> <input type="button" class="btn btn-primary" style="width: 48%" value="クリア" /> <input type="button" class="btn btn-primary pull-right" style="width: 48%" x-ng-click="$ctrl.findList()" value="検索" /> </div> </div> </div> </div> </div> … </div> components/customer/customerList.html 検索ボタンが押下され た時に CustomerContollerの findList関数を呼びだす CustomerContoller で定義した検索条件 変数を⼊⼒フィール ドにバインドする
  41. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. 検索処理と画⾯を紐付ける② <div class="container"> …. <table class="table table-striped"> <caption> <input type="button" class="btn btn-primary btn-sm pull-right" x-ng-click="$ctrl.showDialog()" value="新規作成" /> </caption> <thead> <tr> <th>顧客ID</th> <th>顧客名</th> <th>郵便番号</th> <th>住所</th> <th>電話番号</th> <th>性別</th> <th>登録日</th> <th>更新日</th> </tr> </thead> <tbody> <tr x-ng-repeat="customer in $ctrl.customers"> <td>{{customer.customerId}}</td> <td>{{customer.name}}</td> <td>{{customer.zip}}</td> <td>{{customer.address}}</td> <td>{{customer.phone}}</td> <td>{{customer.sex}}</td> <td>{{customer.serverCreateTime}}</td> <td>{{customer.serverUpdateTime}}</td> </tr> </tbody> </table> </div> components/customer/customerList.html 検索結果であるcustomers変数の 値をテーブルの⾏としてヒット件 数分だけ繰り返して表⽰させる 1レコード分のcustomerオ ブジェクトの内容を各列に 表⽰させる
  42. Copyright ©2016, NC Design & Consulting Co., Ltd. All rights

    reserved. AppPotの情報をフォローしてください! @app_pot @NextConceptDC セミナーの情報や、AppPotの新機能のアナウンスなどSNSを使って ⾏っています。ぜひフォローしてください!