AngularJSディレクティブ

ディレクティブは、テンプレートに挿入して使うHTML的なタグや属性を作る方法である。これにより独自の出力をタグとして簡単に表示でき、AngularJSを拡張できる。

ディレクティブの基本と作成

AngularJSではHTMLタグに独自属性を追加したり、タグを作成したりして、HTML内に特殊な機能を割り当てる。このような機能をディレクティブという。

ディレクティブはAngularJSに用意されているだけでなく、自分で作成することもできる。独自ディレクティブを書けば、自分だけのタグを追加できる。

ディレクティブはモジュールに作成する。モジュールオブジェクトのdirectiveメソッドを使う。

モジュール.directive(名前, 関数);

第1引数にはディレクティブ名を指定する。この名前がそのままタグ名や属性名として使える。第2引数にはディレクティブの具体的な処理を行う関数オブジェクトを指定する。

最も簡単な形は、templateという値を持つオブジェクトを返す関数である。

function() {
    return {template: ... 出力内容 ...};
}

templateは出力タグのテンプレートであり、ここに用意した内容がそのままWebページに表示される。

簡単なディレクティブ作成

OK!と出力するOKディレクティブを作ってみよう。次のスクリプトをscript.jsとして保存する。

var myapp = angular.module('myapp',[]);

myapp.directive('ok', function(){
    return {
        template:'<span style="font-size:24pt;color:red;">OK!</span>'
    };
});

HTMLでは次のように使う。

<body ng-app="myapp">
    <h1>ディレクティブ</h1>
    <ok></ok>
</body>

このページを開くと、赤色でOK!が表示される。HTMLに本来存在しない<ok>タグが、通常のHTMLタグに変換されるのである。

<span style="font-size:24pt;color:red;">OK!</span>

このようなディレクティブを使うと、簡単なカスタムタグで複雑な表示も行える。

ディレクティブ要素の操作

通常のHTMLタグでは、開始タグと終了タグの間に値を書いたり、タグに属性を指定したりする。ディレクティブでも同じようなことができる。

そのためには、単純なオブジェクトではなく関数オブジェクトを返す。

function() {
    return function(scope, element, attrs) {
        ... 必要な処理 ...
    };
}

返される関数には3つの引数が渡される。

  • scope: スコープオブジェクト。
  • element: このディレクティブのDOM要素。
  • attrs: 属性情報を扱うオブジェクト。

ディレクティブタグ内のテキストや属性を利用するには、elementattrsを使う。

ディレクティブの作成

前のscript.jsを修正し、属性とタグ内テキストを使うようにする。

var myapp = angular.module('myapp',[]);
 
myapp.directive('ok', function(){
    return function(scope,element,attrs){
        var size = attrs['size'];
        size = size == null ? '24pt' : size;
        var color = attrs['color'];
        color = color == null ? 'red' : color;
        var txt = element[0].textContent;
        var tag = '<span style="font-size:' + size  + ';color:' + color + ';">' + txt + '</span>';
        element[0].innerHTML = tag;
    };
});

sizecolorattrsから取得する。属性が指定されていない場合もあるため、取得した値がないときはデフォルト値を代入している。

タグ内の値は次のように取得する。

var txt = element[0].textContent;

出力するタグ文字列を作り、element[0].innerHTMLに代入すると、<ok>タグの内部が置き換わる。

HTMLへの組み込み

新しいOKディレクティブは次のように使える。

<ok>This is sample!</ok>
<hr>
<ok size="36pt">This is size sample!</ok>
<hr>
<ok color="blue">This is color sample!</ok>
<hr>
<ok color="green" size="48pt">This is full sample!</ok>

sizecolorを指定しない場合は、それぞれ24ptredがデフォルトになる。タグ内のテキストはそのまま表示されるため、文字色とサイズを簡単に設定できる<ok>タグを作れたことになる。

ディレクティブのイベント設定

ディレクティブは表示をカスタマイズするだけではない。タグにイベントを結び付けて、動くディレクティブを作ることもできる。

element引数はDOM要素なので、通常のイベント設定と同じように扱える。

var myapp = angular.module('myapp',[]);
 
myapp.directive('click', function(){
    return function(scope, element, attrs){
        element[0].addEventListener("click", function(){
            var txt = this.textContent;
            alert('you click "' + txt + '"!');
        }, false);
    };
});

これはクリックするとalertを表示する<click>タグディレクティブである。

<click>This is click sample!</click>

テキスト部分をクリックすると、アラートが表示される。

属性ディレクティブの作成

タグ全体をディレクティブにするだけでなく、属性としてディレクティブを作ることもできる。属性ディレクティブは、さまざまなHTMLタグに追加して使える点が利点である。

モジュール.directive(名前, 
    function() {
        return {
        restrict: 'A',
        template: 出力内容
        };
    });

restrictはディレクティブをどこで使えるかを示す。

  • E: 要素として使用できる。<ok>のような形である。
  • A: 属性として使用できる。<p ok>のような形である。
  • AE: 両方で使用できる。

restrict:'A'を指定すると、属性として使うディレクティブを作成できる。

myapp.directive('ok', function(){
    return {
        restrict: 'A',
        template:function(scope, element){
            var size = 24;
            switch(element['ok']){
            case 'large':
                size = 48; break;
            case 'midium':
                size = 36; break;
            case 'small':
                size = 24; break;
            }
            var tag ='<span style="font-size:' + size
                + 'pt">' + scope[0].textContent
                + '</span>';
            return tag;
        }
    };
});

次のように使用する。

<div ok="large">This is Large sample!</div>
<div ok="midium">This is Midium sample!</div>
<div ok="small">This is Small sample!</div>

templateに関数を指定する場合、scopeelementが渡される。属性値はelement['ok']のように取得し、タグ内テキストはscope[0].textContentから取得する。

属性ディレクティブは主となるタグに追加するものなので、タグ全体を大きく変更するより、何かを追加する程度に設計するのがよい。丸ごと変更するなら要素ディレクティブとして作るほうが適している。