LoginSignup
4
4

More than 5 years have passed since last update.

[AngularJS] 7. ディレクティブ

Last updated at Posted at 2016-01-12

目次
≪前の記事 6.カスタムフィルタ
≫次の記事 8.カスタムディレクティブ


ディレクティブとは

ディレクティブは、AngularJSテンプレートを記述するためにHTMLを拡張したものです。
記述方法によって3種類あります。

  • HTML要素
  • HTML属性
  • クラス値

これまでの例ではHTML属性のタイプしか使用していませんが、その他にHTMLタグ、クラス値として記述するものがあります。これらいずれも ディレクティブ と呼びます。

ディレクティブの名前

これまでディレクティブは ng-xxxx-yyyy という書き方をしてきました。
しかしディレクティブ名の本名は ngXxxxYyyy というキャメルケースで表されます。

  • ng-controller → 本名 ngController
  • ng-model → 本名 ngModel
  • ng-bind-html → 本名 ngBindHtml

といった具合です。

また、テンプレート内での以下の記述は、どれも同じディレクティブを意味しています。

  • x-ng-model
  • data-ng-model
  • ng:model
  • ng_model
  • ng-model

これらはすべて ngModel ディレクティブに正規化されます。

  • 先頭の x- および data- を取り除く
  • :, _, - の区切りを取り除いてキャメルケース化する

これらの記述は、何らかの理由でディレクティブ名がそのまま使用できない場合に有用です。たとえばHTML要素名や属性名と同じ名前(例:table, name, idなど)のディレクティブの場合などです。

主な組み込みディレクティブ

AngularJSには多数の組み込みディレクティブがあります。
ここではこれまで出てきたもの以外でよく使われるディレクティブをいくつかご紹介します。
その他のディレクティブについては こちら を参照してください。

ngClass

ngClass書式
<要素 ng-class="{式}"> .... </要素>

式の結果をclass属性にセットします。
演算結果や条件式、関数の返り値などでclassを変化させることが出来ます。

ngClass例
<p ng-class="flag ? 'is-true' : 'is-false'">
    <input type="checkbox" ng-model="flag">
    チェックボックスon/offでclassが変化する
</p>

ngRepeat | ngRepeatStart | ngRepeatEnd

要素を繰り返す、いわゆる繰り返し制御を行うディレクティブです。

  • ngRepeat
    • ngRepeat が指定された要素を繰り返します
  • ngRepeatStart | ngRepeatEnd
    • ngRepeatStart が指定された要素から、ngRepeatEnd が指定された要素までの間を繰り返します。

ngRepeatの繰り返しは、PHPのforeach文のように、配列やハッシュオブジェクト(合わせてコレクションと言います)に基づいて行われます。

書式(1)

ngRepeat書式(1)
<要素 ng-repeat="変数 in コレクション"> ... </要素>

要素をコレクションの要素数だけ繰り返します。
繰り返し毎にコレクションの要素を変数にセットします。

ngRepeat例(1)
<ul>
    <li ng-repeat="item in collection">{{item}}</li>
</ul>

書式(2)

ngRepeat書式(2)
<要素 ng-repeat="(キー変数, 要素変数) in コレクション"> ... </要素>

この書式では、繰り返し毎にコレクションのキーと要素それぞれ キー変数要素変数にセットします。

ngRepeat例(2)
<ul>
    <li ng-repeat="(key, item) in collection">{{key}}: {{item}}</li>
</ul>

書式(3)

ngRepeat書式(3)
<要素 ng-repeat-start="(キー変数, 要素変数) in コレクション"> ... </要素>
...
<要素 ng-repeat-end>

ngRepeatでは1つの要素の繰り返ししかできませんが、ngRepeatStartとngRepeatEndを使用することで、複数の要素を繰り返すことができます。

ngRepeat例(3)
<dl>
    <dt ng-repeat-start="(key, item) in collection">{{key}}</dt>
    <dd ng-repeat-end>{{item}}</dd>
</dl>

特別な変数

繰り返しの名がでは、以下の特別な変数を利用することが出来ます。

  • $index
    • 何回目の繰り返しかを表します(0から開始)
  • $first
    • 繰り返しの最初であればtrue
  • $middle
    • 繰り返しの間(最初と最後ではない)ときにtrue
  • $last
    • 繰り返しの最後であればtrue
  • $even
    • $indexが偶数であればtrue
  • $odd
    • $indexが奇数であればtrue

ngClassEven | ngClassOdd

ngClassのサブセットで、ngRepeatの繰り返し内で利用できるディレクティブです。
それぞれ繰り返しの偶数回/奇数回でセットするclassを指定することができます。

ngRepeat例(4)
<ul>
    <li ng-repeat="item in collection" 
        ng-class-even="'is-even'" ng-class-odd="'is-odd'">{{item}}</li>
</ul>

ngSwitch

switch構文と同じ働きをするディレクティブです。

ngSwitch書式
<要素 ng-switch="式">
    <子要素 ng-switch-when="値1"> ... </子要素>
    <子要素 ng-switch-when="値2"> ... </子要素>
    <子要素 ng-switch-default> ... </子要素>
</要素>

ng-switchで指定した式の値が、ng-switch-whenで指定された値と等しければ、その子要素が表示されます。
どのng-switch-whenにもマッチしなければ、ng-switch-defaultの子要素が表示されます。

ngSwitch例
<select ng-model="selection">
    <option value=""></option>
    <option value="red"></option>
    <option value="blue"></option>
    <option value="green"></option>
</select>
<p ng-switch="selection">
    <span ng-switch-when="red">赤を</span>
    <span ng-switch-when="blue">青を</span>
    <span ng-switch-when="green">緑を</span>
    <span ng-switch-default></span>
    選択
</p>

ngHref

href属性にバインドタグ{{...}}を含めると、期待通りの動作をしない場合があります。
バインドタグを含める場合はngHref属性を使いましょう。

ngHref例
<a ng-href="http://foo.bar/?param={{param}}">リンク</a>

ngSrc

href属性と同様、src属性でも問題が生じる場合があります。

ngSrc例
<img ng-src="http://foo.bar/?param={{param}}">

HTML要素ディレクティブ

AngularJSでは要素型ディレクティブを用いて、いくつかのHTML要素の振る舞いを変更しています。

a

AngularJSテンプレート内のa要素では、href属性が空の場合にページ遷移やリロードなどのアクションを行わないようになっています。したがってng-clickでのイベント処理時に気を遣わずに済みます。

form

初めの一歩でも述べたように、form要素は FormController をオブジェクト化したディレクティブになっています。

また、HTMLのform要素と異なり、action属性が必須では無く、action属性が空の場合もsubmitによる送信アクションが行われなくなっています。

class

form要素には以下のclassが自動的にセットされます。

  • フォームが手つかずのとき ... ng-pristine
  • フォームに手が加えられているとき ... ng-dirty
  • フォームの入力値がすべて適正なとき ... ng-valid
  • フォームのいずれかの入力値が不適正なとき ... ng-incalid

name属性

form要素にname属性が指定されると、スコープ内に指定された名前で FormControllerオブジェクト がセットされ、FormControllerオブジェクトに直接アクセスできるようになります。

FormControllerプロパティ

name属性値.プロパティ名でアクセス可能です。

  • $pristine ... フォームが手つかずのときにtrue
  • $dirty ... フォームに手が加えられているときにtrue
  • $valid ... フォームの入力値が全て適正なときにtrue
  • $invalid ... フォームのいずれかの入力値が不適正なときにtrue
  • $error ... フォームのいずれかの入力値が不適正なときに {エラー名: [エラーとなっているフォーム要素または入力要素, ...], ...}の形のハッシュオブジェクト

各入力要素(input | textarea | select)

フォーム入力要素もディレクティブ化されています。
以下は各入力要素で共通の属性ディレクティブです。

ngModel

初めの一歩で解説したように、データモデルとの紐付けを行うディレクティブ属性です。

name

AngularJSではname属性をFormControllerオブジェクト内でのプロパティ名として使用します。

FormControllerオブジェクト.name属性値

とすることで入力要素自身のオブジェクトにアクセスすることができます。

また前述の $pristine$dirty$valid$invalid$errorの各プロパティも含まれており、

FormControllerオブジェクト.name属性値.$xxxx

とすることでアクセス可能です。

required

入力必須項目であることを示します。
入力が無い場合にバリデーション・エラーとなります。

input type="text | password | email | url" | textarea

以下はtype="text"type="password"type="email"type="url"のinput要素、およびtextarea要素で使用可能な属性ディレクティブです。

ngMinlength

最小文字数を指定します。入力文字数が指定した値より小さい場合はinvalid(不適正)となります。

ngMaxlength

最大文字数を指定します。入力文字数が指定した値より大きい場合はinvalid(不適正)となります。

ngPattern

正規表現を指定することで入力文字列のパターンチェックを行います。パターンにマッチしない場合にinvalid(不適正)となります。

type="email"type="url"の場合は、HTML5の動作によってそれぞれ適切な入力のみが受け付けられます。HTML5が受け付けた入力からさらに妥当性を絞り込み対場合にngPatternを使用します。

ngTrim

AngularJSでは入力値の前後のホワイトスペースを削除(トリミング)します。
ngTrimにfalseを指定するとトリミングを行わなくなります。

input type="number"

以下は、数字入力用のtype=numberのinput要素で使用可能な属性ディレクティブです。
type=numberはHTML5の動作によって数字のみが受け付けられます。

min

最小値を指定します。指定した値より小さい場合はinvalid(不適正)となります。

max

最大値を指定します。指定した値より大きい場合はinvalid(不適正)となります。

input type="checkbox"

ngTrueValue

チェックボックスがチェックされているときの入力値(value値)を指定します。

ngFalseValue

チャックボックスがチェックされていない時の入力値(value値)を指定します。

input type="radio"

ngValue

等時をボタンがチェックされた場合の値を、式で指定することができます。
value属性との併用はできません。

select

select要素ディレクティブでは、ngOptions属性によりoption要素およびoptgroup要素を自動的に生成します。

ngOptions

コレクション(配列、ハッシュオブジェクト)にもとづいて、option要素、optgroup要素を生成するディレクティブです。

ngOptionsの書式

選択項目 for 要素変数 in コレクション

"選択値 as ラベル for 値 in 配列"
"ラベル group by グループ for 値 in 配列"
```

フォーム&入力要素の例

フォーム&入力要素の例
<h2>form</h2>
<form name="form">
    <p ng-show="form.$invalid">不適正な入力あり</p>
    <p>
        テキスト:<input type="text" ng-model="text" name="text" required ng-maxlength="10" ng-pattern="/^[A-Za-z0-9]+$/">
        <span ng-show="form.text.$error.required">未入力</span>
        <span ng-show="form.text.$error.maxlength">文字数オーバー</span>
        <span ng-show="form.text.$error.pattern">英数字以外の文字</span>
    </p>
    <p>
        メールアドレス:<input type="email" ng-model="email" name="email" required>
        <span ng-show="form.email.$error.required">未入力</span>
    </p>
    <p>
        数字:<input type="number" ng-model="number" name="number" min="10" max="20"> ※10〜20
        <span ng-show="form.number.$invalid">範囲外の数字</span>
    </p>
    <p>
        <input type="radio" ng-model="check" value="OK">OK
        <input type="radio" ng-model="check" value="NG">NG<br>
        OKを選択すると↓がチェックされる
    </p>
    <p>
        チェックすると↑でOKが選択される<br>
        <input type="checkbox" ng-model="check" ng-true-value="'OK'" ng-false-value="'NG'"> OK
    </p>
    <p>
        配列タイプ:
        <select ng-model="arraySelect" ng-options="item for item in arrayCollection"></select><br>
        ハッシュタイプ:
        <select ng-model="hashSelect" ng-options="key as item for (key, item) in hashCollection"></select><br>
        グループタイプ:
        <select ng-model="groupSelect" ng-options="key as item.name group by item.group for (key, item) in groupCollection"></select><br>
    </p>
</form>

サンプルコード

sample07.html
<!DOCTYPE html>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script>
/**
 * アプリケーション モジュール オブジェクトの定義
 */
SampleModule = (function() {
    var module = angular.module("sampleModule", []);

    return module;
})();

/**
 * コントローラの定義
 */
(function(module) {
    /**
     * SampleController
     */
    module.controller("sampleController", function($scope){
        $scope.hashCollection  = {list1: "リスト1", list2: "リスト2", list3: "リスト3"};
        $scope.arrayCollection = ["要素1", "要素2", "要素3"];
        $scope.groupCollection = {
            list1: {name: "リスト1", group: "グループ1"},
            list2: {name: "リスト2", group: "グループ1"}, 
            list3: {name: "リスト3", group: "グループ2"},
            list4: {name: "リスト4", group: "グループ2"},
        };
    });
})(SampleModule);
</script>

<style>
    p.is-true {
        color: red;
    }
    p.is-false {
        color: black;
    }
    li.is-even {
        color: blue;
    }
    li.is-odd {
        color: green;
    }
</style>
<!-- sampleModule テンプレート -->
<div ng-app="sampleModule">
    <!-- sampleController テンプレート -->
    <div ng-controller="sampleController" ng-cloak>
        <h2>ngClass</h2>
        <p ng-class="flag ? 'is-true' : 'is-false'">
            <input type="checkbox" ng-model="flag">
            チェックボックスon/offでclassが変化する
        </p>

        <h2>ngRepeat</h2>
        <h3>例(1)</h3>
        <ul>
            <li ng-repeat="item in hashCollection">{{item}}</li>
        </ul>
        <h3>例(2)</h3>
        <ul>
            <li ng-repeat="(key, item) in hashCollection">{{key}}: {{item}}</li>
        </ul>
        <h3>例(3)</h3>
        <dl>
            <dt ng-repeat-start="(key, item) in hashCollection">{{key}}</dt>
            <dd ng-repeat-end>{{item}}</dd>
        </dl>
        <h3>例(4)</h3>
        <ul>
            <li ng-repeat="item in hashCollection" ng-class-even="'is-even'" ng-class-odd="'is-odd'">{{item}}</li>
        </ul>

        <h2>ngSwitch</h2>
        <select ng-model="selection">
            <option value=""></option>
            <option value="red"></option>
            <option value="blue"></option>
            <option value="green"></option>
        </select>
        <p ng-switch="selection">
            <span ng-switch-when="red">赤を</span>
            <span ng-switch-when="blue">青を</span>
            <span ng-switch-when="green">緑を</span>
            <span ng-switch-default></span>
            選択
        </p>

        <h2>form</h2>
        <form name="form">
            <p ng-show="form.$invalid">不適正な入力あり</p>
            <p>
                テキスト:<input type="text" ng-model="text" name="text" required ng-maxlength="10" ng-pattern="/^[A-Za-z0-9]+$/">
                <span ng-show="form.text.$error.required">未入力</span>
                <span ng-show="form.text.$error.maxlength">文字数オーバー</span>
                <span ng-show="form.text.$error.pattern">英数字以外の文字</span>
            </p>
            <p>
                メールアドレス:<input type="email" ng-model="email" name="email" required>
                <span ng-show="form.email.$error.required">未入力</span>
            </p>
            <p>
                数字:<input type="number" ng-model="number" name="number" min="10" max="20"> ※10〜20
                <span ng-show="form.number.$invalid">範囲外の数字</span>
            </p>
            <p>
                <input type="radio" ng-model="check" value="OK">OK
                <input type="radio" ng-model="check" value="NG">NG<br>
                OKを選択すると↓がチェックされる
            </p>
            <p>
                チェックすると↑でOKが選択される<br>
                <input type="checkbox" ng-model="check" ng-true-value="'OK'" ng-false-value="'NG'"> OK
            </p>
            <p>
                配列タイプ:
                <select ng-model="arraySelect" ng-options="item for item in arrayCollection"></select><br>
                ハッシュタイプ:
                <select ng-model="hashSelect" ng-options="key as item for (key, item) in hashCollection"></select><br>
                グループタイプ:
                <select ng-model="groupSelect" ng-options="key as item.name group by item.group for (key, item) in groupCollection"></select><br>
            </p>
        </form>
    </div>
</div>

目次
≪前の記事 6.カスタムフィルタ
≫次の記事 8.カスタムディレクティブ


4
4
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
4
4