検証に利用したAngularJSアプリのコードについて
基本コード
今回は検証が目的だったため、単純なシングルページアプリケーションを作成しました。下記のコードはサンプルです。実際に検証したコードと構造は同様ですが、細かい機能はすべて省略しています。
HTMLファイル
sample.html
形式としては一つのHTMLファイル内にng-templateを使い、各種テンプレートを記載しています。
<!DOCTYPE html>
<html ng-app="sampleApp">
<head>
<title>{{$root.title}}|sample site</title>
<meta name="description" content="{{$root.description}}">
<!--OGP TwitterCard の設定-->
<link href="http://example.com/css/common.css" type="text/css" rel="stylesheet">
</head>
<body>
<div ng-view></div>
<!--
=============================================
list pageのtemplate
=============================================
-->
<script id="listCtrl.html" type="text/ng-template">
<section>
<h1>サンプル一覧 No1</h1>
<ul ng-repeat="item in items">
<li><a href="#/end/{{item.id}}/">{{item.name}}</a></li>
</ul>
</section>
</script>
<!--
=============================================
End pageのtemplate
=============================================
-->
<script id="endCtrl.html" type="text/ng-template">
<section>
<h1>{{item.name}}</h1>
<img ng-src="{{item.img}}" alt="{{item.name}}">
<p>{{item.text}}</p>
</section>
</script>
<script src="http://example.com/js/common.js"></script>
<script src="http://example.com/js/sample/router.js"></script>
<script src="http://example.com/js/sample/listModel.js"></script>
<script src="http://example.com/js/sample/listCtrl.js"></script>
<script src="http://example.com/js/sample/endCtrl.js"></script>
</body>
</html>
JSファイル
common.js
angular.jsや共通的に使うconfig、$resourceの設定を記載したJSファイルを格納しています。
router.js
router処理を記載しています。list、endのルーティングを設定しています。
var app = angular.module("sampleApp", ["ngRoute","commonModule"]).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'listCtrl.html',
controller: 'listCtrl',
reloadOnSearch: false
}).
when('/end/:id/', {
templateUrl: 'endCtrl.html',
controller: 'endCtrl',
reloadOnSearch: false
}).
otherwise({redirectTo : '/'});
}]);
listCtrl.js
listページのController。listModelからコンテンツデータを取得しScopeに格納しています。
var controller = function($rootScope, $scope, listModel){
//scope設定
$rootScope.title = "タイトル";
$rootScope.description = "タイトルの一覧ページです。";
$scope.items = listModel.get();
//JSONデータを取得し、scopeに格納
listModel.fetch().then(function(resp){
$scope.items = listModel.get();
});
};
controller.$inject = ['$rootScope','$scope', 'listModel'];
app.controller('listCtrl', controller);
endCtrl.js
endページのController。listModelからコンテンツデータを取得しScopeに格納しています。
var controller = function($rootScope, $scope, $routeParams, listModel){
//scope設定
$scope.item = {};
$scope.id = $routeParams.id;
//JSONデータを取得し、scopeに格納
listModel.fetch().then(function(resp){
$scope.item = listModel.get($scope.id);
$rootScope.title = $scope.item.name;
$rootScope.description = $scope.item.name + "について紹介。";
});
};
controller.$inject = ['$rootScope','$scope', '$routeParams', 'listModel'];
app.controller('endCtrl', controller);
listModel.js
コンテンツデータを記載しているJSONファイルを取得し、指定の形式で返却しています。
var model = function($http, $q, list01Resource){
this.datas = [];
//データの読み込みmethod
this.fetch = function(){
var that = this,
deferred = $q.defer();
//api
//list01用のコンテンツデータが記載されたJSONファイルを取得
list01Resource.get({}, function(resp) {
that.datas = resp;
deferred.resolve(resp);
//error
}, function(){
deferred.reject({});
});
return deferred.promise;
};
//データの取得method
this.get = function(id){
if(id){
var result = null;
for (var i = 0; i < this.datas.length; i++) {
if(this.datas[i].id === id){
result = this.datas[i];
break;
}
}
return result;
}
return this.datas;
};
};
model.$inject = ['$http', "$q", "list01Resource"];
app.service('listModel', model);
条件に応じたコードの変更点
HTML5モード
通常のhash形式とpushStateでの挙動の差異を把握するために、pushStateに関しては下記のコードをrouter.jsのconfigに追記しています。
$locationProvider.html5Mode(true);
レンダリング済みのLISTのHTMLを埋め込む
AngularJSで生成したHTMLを把握できず、Endページをクロールしない想定がありましたので、レンダリング済みのListのHTMLを記載しています。Endアクセス時にもレンダリング済みのListのHTMLが表示されますが、意図的に行っています。その状態でインデックスにどのような変化が起きるのかを検証するためです。
<!DOCTYPE html>
<html ng-app="sampleApp">
<head>
~~ 省略 ~~
</head>
<body>
<div ng-view>
<section>
<h1>サンプル一覧 No3</h1>
<ul>
<li><a href="#/end/1/">サンプル一覧 No3 詳細1</a></li>
<li><a href="#/end/2/">サンプル一覧 No3 詳細2</a></li>
<li><a href="#/end/3/">サンプル一覧 No3 詳細3</a></li>
</ul>
</section>
</div>
~~ ng-template 記載 ~~
</body>
</html>
リストのng-templateを埋め込む
こちらに関しては、AngularJSのテンプレート変数がどのように解釈されるか興味があったため、作成しました。想定としては、/end/{{item.id}}/に対してクローラーが回り、検索結果に表示されるバグが生じるのではないかと予測しました。
<!DOCTYPE html>
<html ng-app="sampleApp">
<head>
~~ 省略 ~~
</head>
<body>
<div ng-view>
<section>
<h1>サンプル一覧 No2</h1>
<ul ng-repeat="item in items">
<li><a href="#/end/{{item.id}}/">{{item.name}}</a></li>
</ul>
</section>
</div>
~~ ng-template 記載 ~~
</body>
</html>
