SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

AngularJSではじめるJavaScriptフレームワーク開発スタイル

AngularJSでカスタムディレクティブを作ってみよう

AngularJSで初めるJavaScriptフレームワーク開発スタイル 第11回

コントローラとテンプレートを組み合わせたディレクティブを作成する

 3つめのサンプルは、HTMLテンプレートとコントローラをセットにしたカスタムディレクティブの作成です。この組み合わせでカスタムディレクティブが作成できるようになれば、部品化したディレクティブとして管理ができるようになります。

 今回作成するサンプルは、図3のようにテキストフィールドに入力した文字を利用して、「こんにちは、XXさん」のように表示します。

図3 サンプルコードの実行例
図3 サンプルコードの実行例

 最初に表示される名前は、属性値を利用して指定できることと、実際のHTMLは別のテンプレートで管理します。従って、実際に利用する場合には、リスト5のように非常にシンプルなテンプレートになります。

リスト5 HTMLテンプレート(template/index.html)
<!DOCTYPE html>
<html lang="ja" ng-app="template">
<head>
    <meta charset="UTF-8">
    <title>My Template Directive</title>
    <script type="text/javascript" src="../vendors/angular.js"></script>
    <script type="text/javascript" src="template.js"></script>
</head>
<body>
    <my-template default="ゲスト" />  <!-- (1)myTemplateディレクティブの利用 -->
</body>
</html>

 今回、作成したディレクティブの名称はmyTemplateのために(1)のように"my-template"タグとして指定します。実際にこのタグ内に表示するためのテンプレートはリスト6のようになります。また、前回までは属性として指定していましたが、デフォルトでは属性で指定することも、要素名でも指定することもできますが、今回は要素名でのみ指定可能としますので、この指定もディレクティブの作成時に行います。

リスト6 ディレクティブ内で使用するHTMLテンプレート(template/template.html)
<div>
    <div>あなたの名前をいれてください</div>
    <input type="text" ng-model="name" />
    <hr />
    <h1 class="message" ng-show="showMessage">こんにちは「{{ name }}」さん</h1>
</div>

 myTemplateディレクティブを実装したコードがリスト7のようになります。

リスト7 テンプレートとコントローラを利用したディレクティブの実装(template/template.js)
(function(){
    'use strict';
    angular.module('template',[])
        .directive('myTemplate',[templateDirective]);

    function templateDirective(){
        // (1)ディレクティブの作成に必要なオブジェクトを返す
        return {
            controller : ['$scope',templateController], //(2)(6)で定義したコントローラを指定する
            scope: {
                default : '@'   // (3)default属性の値をそのまま利用する
            },
            restrict: 'E',      // (4)要素名(E)のみを指定する
            templateUrl : 'template.html',  // (5)テンプレートファイル名を指定する
            link : function(scope,element){
                scope.showMessage = false;
                scope.$watch('name',function(val){
                    if(val){
                        scope.showMessage = true;
                    }
                    else{
                        scope.showMessage = false;
                    }
                });
            }
        }
    }
    // (6)利用するコントローラを定義する
    function templateController($scope){
        // (7)default属性の値は$scope変数として利用出来る
        $scope.name = $scope.default;
    }
}());

 (1)ではディレクティブの作成に必要なプロパティを指定したオブジェクトを返します。このプロパティはディレクティブ作成時に指定できるプロパティのように非常にたくさんありますが、今回は、controller、restrict、scope、templateUrl、linkプロパティを使用します。今までの例では、関数のみを定義していましたが、この場合にはlinkプロパティのみを指定していることと同じになります。

 それぞれのプロパティを一つずつ説明していきます。

 まず、(2)のcontrollerプロパティは、実際にmyTemplateで利用するコントローラを指定します。実際のコントローラの定義は(6)で行っています。今までの通常のコントローラの作成方法に慣れていれば、同様に行えるので直感的に理解が可能かと思います。

 続いて、scopeです。このscopeプロパティが最も理解が難しいプロパティで、以下のような指定ができます。

表2 scopeプロパティに指定可能な値
指定できる値 説明
false 現在のscopeオブジェクトをそのまま利用する。(デフォルト)
true 親のscopeオブジェクトを継承した新しいscopeオブジェクトを作成する。
{...} 独立したscopeオブジェクトを作成する。

 falseの場合には、一般的にそのディレクティブが使われている上位タグのコントローラのscopeオブジェクトと同じオブジェクトになります。trueの場合は、親scopeオブジェクトを継承した形で新たなscopeオブジェクトが作成されます。ngControllerディレクティブがtrueを指定しているよいサンプルです。

 そして、オブジェクト形式として指定した場合には、まったく独立したscopeオブジェクトが作成されます。部品として定義したい場合には、独立性を高くしたいのでこのような指定が通常になります。また、(3)ではdefaultの値として「@」のように記号の値を指定しています。これは、テンプレートでdefault属性として指定した値をそのまま、値としてscopeオブジェクトを作成するように指定です。従って、(7)では$scope.defaultという値はテンプレートで指定した「ゲスト」という文字列が設定されます。また、「@」以外の記号も利用でき、表3のように他の記号も利用可能です。

表3 指定できる記号
記号 説明
'@' 指定した値を文字列として取得できる。ただし、{{Angular式}}のように指定すれば、Angular式として評価後の値を取得できる。
'=' 指定した変数を双方向バインディング可能な変数として利用可能である。また、指定した値はAngular式として評価して値を取得できる。
'&' 指定した文字列をAngular式のFunctionとして取得できる。

 '@default'のように記号+属性名でも指定が可能です。その場合、scopeオブジェクトの変数名とディレクティブの属性名を別に管理ができます。指定しなかった場合には、変数名=属性名として扱われます。ただし、属性名はディレクティブ名と同様にcamelCaseとして記述します。

 続いて、(4)のrestrictは、作成したディレクティブを属性名や、要素名、クラス名として指定ができるもので、以下の指定が行えます。

表4 restrictで指定できるタイプ
タイプ 説明
'E' 要素(Element)名として指定ができる。
'A' 属性(Attribute)名として指定ができる。
'C' クラス(Class)名として指定ができる。
'M' コメントとして指定がでできる。

 また、デフォルトは'EA'のように指定したものと同じです。

 そして、最後が(5)のtemplateUrlは、テンプレートURLを指定します。テンプレートの内容は、リスト6のように、通常のAngularJSで利用するテンプレートのフォーマットが利用できますので、ngIncludeで管理していたテンプレートの移行が容易にできます。ただし、相対パスでの指定の場合には実行しているHTMLからの相対パスになるので注意してください。

 また、関数も指定でき、リスト8のように動的にテンプレートURLを変えることもできます。この際に引数のelementとattrsはlink関数の引数で使用したものと同じです。

リスト8 テンプレートのURLに関数を指定する場合の例
templateUrl : function(element,attrs){
    return 'template_' + attrs['lang'] + '.html';
}

最後に

 簡単なカスタムディレクティブから、少々複雑なカスタムディレクティブまでの作成方法を紹介しました。ここまで出来るようになれば、かなりのディレクティブが自分で作成できるようになると思います。

 各プロパティなどの詳細な記述方法や説明は割愛させていただきましたが、あとはドキュメントを見ながら足りない部分を補っていけると思います。ぜひ、カスタムディレクティブを作成して、独立性や再利用性が高いプログラミングに挑戦してみてください。

参考資料

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
AngularJSではじめるJavaScriptフレームワーク開発スタイル連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 小林 昌弘(コバヤシ マサヒロ)

WINGSプロジェクト について> 有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/8845 2015/07/31 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー