39
39

More than 5 years have passed since last update.

AngularJS 入門 - Directive

Last updated at Posted at 2013-12-11

前回の続きです。

今回はDirective(ディレクティブ)についてです。

ngModelngRepeatなどを既に使っているのでディレクティブがどんなものかは大体分かっているかと思います。

ビルドインのディレクティブ一覧 => http://docs.angularjs.org/api/ng#directive

なので早速ですがディレクティブを作ります。

単純なディレクティブ

レイアウトを持たず、動作を追加するディレクティブを作ってみます。

ちょうどTwitter Bootstrapが雛形に使われているので、リンクにツールチップを追加します。

app/views/main.html
<p>
    <input type="text" ng-model="world">
    <span ng-click="addFramework(world)" class="btn btn-primary">Add</span>
</p>
<p>Hello {{ world }}!</p>

<div>
    <h3>{{ frameworks.length }} frameworks</h3>
    <input type="text" ng-model="searchText" />
    <span ng-hide="frameworks">読み込み中...</span>
    <ul>
        <li ng-repeat="f in frameworks | reverse | filter:searchText">
            <!— tooltip属性を追加する >
            <a ng-href="/#/frameworks/{{f}}" tooltip>{{f|uppercase}}</a>
        </li>
    </ul>
</div>

tooltipディレクティブを定義します。

app/scripts/app.js
/* jshint indent: 4, unused: false */
'use strict';

angular.module('angularSampleApp', [
        'ngCookies', 'ngResource', 'ngSanitize', 'ngRoute'
    ])
    .factory(‘…’, function () {})
    // tooltip ディレクティブを定義
    .directive('tooltip', function () {
        return function (scope, element, attr) {

            element.tooltip({
                title: 'tooltip test'
            });

        };
    });

省略型はクロージャを返却して定義とします。
この場合はtooltipディレクティブが設定されているDOMに対して、ツールチップを表示するだけです。

scope element attr は インジェクターからインジェクトされた物ではないです。

名称未設定-2.png

elementはただのjQueryオブジェクトなので、DOM操作はなんでもできますね!

ディレクティブにパラメータを渡す

先ほど作ったディレクティブを少し弄ります。

app/views/main.html
<p>
    <input type="text" ng-model="world">
    <span ng-click="addFramework(world)" class="btn btn-primary">Add</span>
</p>
<p>Hello {{ world }}!</p>

<div>
    <h3>{{ frameworks.length }} frameworks</h3>
    <input type="text" ng-model="searchText" />
    <span ng-hide="frameworks">読み込み中...</span>
    <ul>
        <li ng-repeat="f in frameworks | reverse | filter:searchText">
            <!— ディレクティブに変数を渡す >
            <a ng-href="/#/frameworks/{{f}}" tooltip="f">{{f|uppercase}}</a>
        </li>
    </ul>
</div>

tooltipディレクティブに変数fを渡す。

app/scripts/app.js

    .directive('tooltip', function ($parse) { // expressionを評価するためのサービス
        // オプションを指定する場合はオブジェクトを返す
        return {
            restrict: A,
            link: function (scope, element, attr) {

                // attr.tooltip=“f” を指定したので、fの中身を取得し、ツールチップに設定
                // scope.$eval(attr.tooltip) でもよい
                var value = $parse(attr.tooltip)(scope);

                element.tooltip({
                    title: value
                });

            }
        };
    });

attr.tooltipの中身はただの文字なので、評価した結果をツールチップに渡します。

名称未設定-1.png

値の変更を監視してjsを実行したい場合は、scope.$watch() を使えばよいです。
http://docs.angularjs.org/api/ng.$rootScope.Scope#methods_$watch

restrict?

ディレクティブのrestrictはディレクティブの対象を制限する為に使います。

  • E <some-directive></some-directive>
  • A <div some-directive=“”></div>
  • C <div class=“some-directive”></div>
  • M <!-— directive: some-directive -—>

複数指定する場合は restrict: ‘AEC’ の様に繋げて書きます。

テンプレート

ディレクティブにはテンプレートの機能があります。

app/scripts/app.js

    .directive('tooltip', function ($parse) {
        return {
            restrict: 'A',
            // テンプレートを追加
            template: '<span class="glyphicon glyphicon-asterisk"></span>',
            link: function (scope, element, attr) {

                var value = $parse(attr.tooltip)(scope);

                element.tooltip({
                    title: value
                });

            }
        };
    });

名称未設定-1.png

一応これだけでテンプレートが反映されますが、固定文ではダメなのでngTranscludeを使います。

ngTransclude

app/scripts/app.js

    .directive('tooltip', function ($parse) {
        return {
            restrict: 'A',
            // テンプレートを編集
            template: '<span class="glyphicon glyphicon-asterisk"></span> <i ng-transclude></i>',
            // transcludeを設定
            transclude: true,
            link: function (scope, element, attr) {

                var value = $parse(attr.tooltip)(scope);

                element.tooltip({
                    title: value
                });

            }
        };
    });

名称未設定-2.png

テンプレートのどこに内容をセットするかをngTranscludeで指定するだけなので簡単です。

ディレクティブ間の連携

公式ドキュメント(http://docs.angularjs.org/guide/directive#creating-custom-directives_demo_creating-directives-that-communicate)にいい感じの説明があるので、今回は省略します。

39
39
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
39