はじめに
AngularJSの1.5.xより component が実装され、巷の噂ではAngularJSはTypeScriptを相性が良いとのことで、実装方法を研究したメモを残す。
開発環境
- VisualStudio 2015
- プロジェクトのプロパティの「TypeScriptビルド」の「出力」項目、「Javascript 出力をファイルに統合する」にチェックを入れ、値を「application.js」にする
- NuGetで、以下のパッケージを読み込む
- es6-promise.TypeScript.DefinitelyTyped (v0.1.3)
- angularjs.TypeScript.DefinitelyTyped (v5.4.2)
- jquery.TypeScript.DefinitelyTyped (v3.0.4)
Viewの実装
単純にcomponentで作成されたタグを表示する
index.html
<!DOCTYPE html>
<html lang="ja" ng-app="app">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="app.css" type="text/css" />
<script src="https://code.jquery.com/jquery-2.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
<script src="application.js"></script>
</head>
<body ng-controller="MainController as main">
<h1 ng-bind="main.title"></h1>
<element-test param-title="main.subTitle" call-back-event="main.callback1(value)"></element-test>
</body>
</html>
element-testの仕様
- param-title : element-testの中で表示するタイトル
- call-back-event : コントローラ側のイベントを呼び出す
モジュール定義
angularのappを定義します
app.ts
/// <reference path="_include.ts" />
module app {
var module = angular.module('app', []);
module.controller('MainController', MainController);
module.component('elementTest', ElementComponentFactory());
}
_include.ts
/// <reference path="scripts/typings/jquery/jquery.d.ts" />
/// <reference path="scripts/typings/angularjs/angular.d.ts" />
/// <reference path="scripts/typings/es6-promise/es6-promise.d.ts" />
/// <reference path="main.controller.ts" />
/// <reference path="element.component.ts" />
メインコントローラ
main.controller.ts
/// <reference path="_include.ts" />
module app {
/**
* メイン コントローラ
*/
export class MainController {
// タイトル
title: string;
// サブタイトル
subTitle: string;
// コールバック
callback1: Function;
/**
* コンストラクタ
*/
constructor() {
this.title = "AngularJS(1.5)でcomponent実装";
this.subTitle = "コントローラから設定したパラメタ";
// コールバックの設定
this.callback1 = (value : any) => {
// コールバックが呼び出される。valueは「1001」
}
}
}
}
コンポーネント
element.component.ts
/// <reference path="_include.ts" />
module app {
/**
* Element コンポーネント作成
*/
export function ElementComponentFactory(): ng.IComponentOptions {
return {
bindings:
{
//コントローラパラメタ
paramTitle: '=',
//コールバック
callBackEvent: '&'
},
template: [
"<div>",
"<p ng-bind='_my.displayItem'></p>",
"<button ng-click='_my.clickButton(123)'>ボタン</button>",
"</div>"
].join(""),
controllerAs: '_my',
controller: ElementComponent
};
}
/**
* コントローラ
* @returns
*/
class ElementComponent {
public static $inject = ['$http']; // httpサービスの注入
/**
* 表示項目
*/
displayItem: string;
/**
* コールバック
*/
callBackEvent: Function;
// タイトル
private _paramTitle: string;
get paramTitle (): string {
return this._paramTitle;
}
/**
* コントローラとのI/O
* @param {string} value
*/
set paramTitle(value: string) {
if (!angular.isDefined(value)) {
return;
}
this._paramTitle = value;
// パラメタが設定された処理
this.displayItem = value;
}
/**
* コンストラクタ
* @param {ng.IHttpService} public $http
*/
constructor(public $http: ng.IHttpService) {
// this.$http で httpサービスが使用可能
}
/**
* ボタンが押された
* @param {number} value 値
*/
clickButton(value: number): void {
// valueは「123」が設定されている
this.callBackEvent({ 'value': 1001 });
this.paramTitle = "ボタン押下";
}
}
}
ポイント
- component の controller は class で実装する
- 従来 $scope 経由で操作していたプロパティ類は、controller class のプロパティで宣言する
- コントローラからの値受信は、 setter の中で処理を行う
- コントローラへの callback は Function型 で定義したプロパティを呼び出す
最後に
自分は、Javascriptと言う言語が気持ち悪くて、コード実装時はモチベーションが事が下がったままでしたが、TypeScriptの場合は綺麗なコードになり、書いてて楽しくなりました。