nkjmkzk.net

powered by Kazuki Nakajima

AngularJSではじめるHTML5開発 – Part4 動的なデータベースアクセスと画面の更新

Part3の続きです。

今回はレコードをクリックするとデータベースから詳細情報を取得し、その詳細情報で画面を更新するという仕組みを実装していきます。

まず今回開発する部分をデモでみておきましょう。

デモ

それでは実装へ。

ゲストオブジェクトに項目(フィールド)を追加する

データベースから詳細情報を取得する、というほどまだオブジェクトには項目がありません。アプケーションで利用できそうなのは自動的に追加された「ゲスト名」くらいです。これでは寂しいのでEmailを保持する項目くらい追加しておきましょう。

スキーマビルダーを起動し、要素タブから「メール」を選択して右側のゲストオブジェクトの上にドラッグ&ドロップします。

drag_email-12

下記のように入力して保存をクリックします。

  • 項目の表示ラベル => Email
  • 項目名 => email

new email field

これで項目が追加されました。

 

レコード詳細情報を取得する関数を作成する

Part2ではRemoteTKのquery()メソッドを用いて、SOQL構文の実行によってデータベースからゲストオブジェクト中のレコード一覧を取得しました。

このquery()を用いて単一のレコード情報を取得することも当然可能ですが、単一のレコードを取得する場合はより簡単なretrieve()というメソッドが用意されているのでこちらを利用することにしましょう。

また、レコード一覧を取得する部分はindexファイルを読み込むやいなや実行されていましたが、今回はクリックのタイミングで実行する必要があるため、外部から呼び出し可能な関数としてまとめておきます。

	ngbootcamp.controller('guestCtl', function($scope){
		$scope.getGuest = function(recordId){
			$scope.force.retrieve(
				"guest__c",
				recordId,
				"Id,Name,email__c",
				function(result){
					$scope.guest = result;
					$scope.$apply();
				},
					function(result){
					console.log(result);
				}
			);
		}

		$scope.getGuests = function(){
			var soql = "select Id, Name, CreatedDate from guest__c";
			$scope.force.query(
				soql,
				function(result){
					$scope.guests = result.records;
					$scope.$apply();
				},
					function(result){
					console.log(result);
				}
			);
		}

		$scope.force = new remotetk.Client();
		$scope.getGuests();
	}

ゲストレコードの詳細を取得する関数、$scope.getGuest()が追加されています。また、先に作成していたゲストレコード一覧を取得するコードも$scope.getGuests()として関数化しています。また、RemoteTKのインスタンスも$scope.forceにセットして各関数から自由に参照できるようにしています。

$scope.getGuest()の内部ではRemoteTKのメソッドであるretrieve()が実行されています。
このメソッドは、第一引数にオブジェクト名、第二引数にレコードID、そして第三引数にカンマ区切りの項目リストをとります。今回はオブジェクト名がguest__c、レコードIDはrecordId、項目リストはIdとName、そしてemail__cということになります。

第四引数、第五引数はquery()と同様、成功時と失敗時のコールバック関数です。
成功時のコールバックでは$scope.guestに取得したデータをセットし、$scope.$apply()でデータモデルに反映させています。

これでレコード詳細を取得する関数は出来上がりました。

 

クリックで関数を実行する仕組み

とっても簡単です。各レコードを表示させている<a>タグにng-clickという属性を追加してあげます。これはJavascriptのonclickと同様の機能を持ちますが、AngularJSで作成した関数を呼べる、というところがポイントです。

				<div class="panel panel-default">
					<div class="panel-heading">
						ゲスト
					</div>
					<div class="list-group">
						<a class="list-group-item" href="#" ng-click="getGuest(guest.Id)" ng-repeat="guest in guests">{{guest.Name}}</a>
					</div>
				</div>

getGuest()の引数にちゃっかりguest.Idが指定されています。これによってどのレコードの詳細を取得すべきか判断しているわけです。

これでレコードがクリックされると先ほど作成した$scope.getGuest()が呼ばれ、データベースからレコードの詳細を取得するようになりました。

 

画面を更新する

この部分が特にAngularJSによってスマートに実装できる部分です。

データベースから取得されたレコード詳細情報は$scope.guestに格納されています。HTML側ではこの変数を参照しておけば値が入ってきた時点で表示されるようになります。

			<div class="col-md-8">
				<h1>{{guest.Name}}</h1>
				<form role="form">
					<div class="form-group">
						<label>ゲスト名</label>
						<input ng-model="guest.Name" type="text" class="form-control" placeholder="ゲスト名" />
					</div>
					<div class="form-group">
						<label>Email</label>
						<input ng-model="guest.email__c" type="email" class="form-control" placeholder="Email" />
					</div>
				</form>
			</div>

<h1>タグ内では{{guest.Name}}を用いてダブル波括弧で変数を参照しています。

インプットフィールドではng-modelを用いてAngularJSの変数にバインドさせています。

実際の動作をプレビューで確認してみましょう。

click record

レコードをクリックすると右列に詳細が表示されるようになっていますね。

ただし、Emailフィールドは空のままです。そりゃそうだ。まだ値自体がデータベースに保存されていませんから。

ということで次回はデータを更新する処理をみていきたいと思います。

例によって現時点でのindexファイルのソースコードを掲載しておきます。

<apex:page showHeader="false" standardStyleSheets="false" applyBodyTag="false" applyHtmlTag="false" docType="html-5.0" >
   
<html ng-app="ngbootcamp">
<head>
    <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.0/css/bootstrap.min.css"></link>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.0/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.10/angular.min.js"></script>
    <c:RemoteTK />
    <script>
    var ngbootcamp = angular.module('ngbootcamp', []);
    
    ngbootcamp.controller('guestCtl', function($scope){
        $scope.getGuest = function(recordId){
            $scope.force.retrieve(
                "guest__c",
                recordId,
                "Id,Name,email__c",
                function(result){
                    $scope.guest = result;
                    $scope.$apply();
                },
                    function(result){
                    console.log(result);
                }
            );
        }
 
        $scope.getGuests = function(){
            var soql = "select Id, Name, CreatedDate from guest__c";
            $scope.force.query(
                soql,
                function(result){
                    $scope.guests = result.records;
                    $scope.$apply();
                },
                    function(result){
                    console.log(result);
                }
            );
        }
 
        $scope.force = new remotetk.Client();
        $scope.getGuests();
    });
    </script>
</head>
<body ng-controller="guestCtl">
    <div class="container" style="margin-top:20px;">
        <div class="row">
            <div class="col-md-4">
                <div class="panel panel-default">
                    <div class="panel-heading">
                        ゲスト
                    </div>
                    <div class="list-group">
                        <a class="list-group-item" href="#" ng-click="getGuest(guest.Id)" ng-repeat="guest in guests">{{guest.Name}}</a>
                    </div>
                </div>
            </div>
            <div class="col-md-8">
                <h1>{{guest.Name}}</h1>
                <form role="form">
                    <div class="form-group">
                        <label>ゲスト名</label>
                        <input ng-model="guest.Name" type="text" class="form-control" placeholder="ゲスト名" />
                    </div>
                    <div class="form-group">
                        <label>Email</label>
                        <input ng-model="guest.email__c" type="email" class="form-control" placeholder="Email" />
                    </div>
                </form>
            </div>
        </div>
    </div>
</body>
</html>
   
</apex:page>

 

関連情報

without comments

Written by 中嶋 一樹

2月 8th, 2014 at 10:39 pm

Leave a Reply