LoginSignup
75
72

More than 5 years have passed since last update.

AngularJS 入門 ~ ルーティング, フィルター

Last updated at Posted at 2013-12-04

「AngularJS 入門」の続きです。

今回はルーティングと、フィルターです。

ルーティング

実は既にルーティングの設定はしてあるので見てみます。

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

angular
    .module('angularSampleApp', [
        'ngCookies', 'ngResource', 'ngSanitize', 'ngRoute'
    ])
    .config(function ($routeProvider) {
        // ルーティング設定
        $routeProvider
            .when('/', {
                templateUrl: 'views/main.html',
                controller: 'MainCtrl'
            })
            .otherwise({
                redirectTo: '/'
            });

    });

ルーティングはURLのマッチングパターンに対して、下記を設定するだけでOKです。

  • コントローラー名
  • ビューのパス

URLのマッチングパターンには パラメーター を受け取るようにする事ができるので、新しく定義してみます。

ルーティングを定義してみる

$routeProviderにルーティング定義を追加

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

angular.module('angularSampleApp', [
        'ngCookies', 'ngResource', 'ngSanitize', 'ngRoute'
    ])
    .config(function ($routeProvider) {
        $routeProvider
            .when('/', {
                templateUrl: 'views/main.html',
                controller: 'MainCtrl'
            })
            // この部分を追加
            .when('/frameworks/:name', {
                templateUrl: 'views/desc.html',
                controller: 'DescCtrl'
            })
            .otherwise({
                redirectTo: '/'
            });
    });

URLのマッチングパターンに:{変数名}を使うと、パラメータとして受け取る事ができます。

ルーティングに定義したDescCtrlを作る

app/scripts/controllers/main.js
/* jshint indent: 4 */
'use strict';

angular.module('angularSampleApp')
    .controller('MainCtrl', function ($scope) {

        $scope.world = 'Angular';

        $scope.addFramework = function (text) {
            $scope.frameworks.push(text);
            $scope.world = '';
        };

    })
    // 新しく追加したコントローラー
    .controller('DescCtrl', function ($scope, $routeParams) {

        $scope.framework = {
            name: $routeParams.name
        };

    });

マッチしたルーティングのパラメータは、$routeParamsサービスから取得できます。

補足
引数の名前は$routeParamsでなければなりません。
位置はどこでもいいのですが、DIの回に説明するのでここでは割愛

ルーティングに定義したapp/views/desc.htmlを作る

app/views/desc.html
<pre>{{ framework }}</pre>

確認できればよいので変数のダンプ

準備ができたのでアクセスしてみます

ブラウザのURLを手動でhttp://127.0.0.1:9000/#/frameworks/hoge等にしてみるとイイ感じに表示されるはずです。
kobito.1386187104.282593.png

ルーティングが完成したので、次はリンクを貼ってみます。

リンクからのアクセス

先程手動でやった事をマークアップするだけでできてしまいます。

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>

<p ng-init="frameworks = ['Backbone.js', 'Ember.js', 'Knockout.js']">
    <h3>{{ frameworks.length }} frameworks</h3>
    <ul>
        <!-- リンクに置き換えます -->
        <li ng-repeat="f in frameworks">
            <a ng-href="/#/frameworks/{{f}}">{{f}}</a>
        </li>
    </ul>
</p>

kobito.1386189294.689709.png

これでリンクが貼れます。

補足
本来はパラメーターをurlエンコードする必要がありますが、ここでは省略しています。

フィルター

データを変換する機構です。
ビュー上でフィルター専用のシンタックスがあるので、便利です。

フィルターを使ってみる

ビュー上で{{ 変数名|フィルター名 }}と記述すると、変数をフィルタリングした結果が表示されます。
もちろん元の変数は不変です。

単純なフィルター

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>

<p ng-init="frameworks = ['Backbone.js', 'Ember.js', 'Knockout.js']">
    <h3>{{ frameworks.length }} frameworks</h3>
    <ul>
        <li ng-repeat="f in frameworks">
            <a ng-href="/#/frameworks/{{f}}">{{f|uppercase}}</a> <!-- 大文字にする -->
        </li>
    </ul>
</p>

kobito.1386189955.911518.png

uppercaseフィルターで大文字が表示されました。

オブジェクトに対するフィルター

フィルターが対応していれば、何に対しても使えます。

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>

<p ng-init="frameworks = ['Backbone.js', 'Ember.js', 'Knockout.js']">
    <h3>{{ frameworks.length }} frameworks</h3>
    <ul>
        <li ng-repeat="f in frameworks | filter:'a'"> <!-- 文字'a'が含まれている要素のみ表示 -->
            <a ng-href="/#/frameworks/{{f}}">{{f|uppercase}}</a>
        </li>
    </ul>
</p>

kobito.1386190803.164149.png

'a'が含まれるBackbone.jsだけが表示されました。

ここではリテラルを書きましたが、フィルターに渡す値に変数を使う事ができます。

リアルタイムにフィルタリング

入力した値からリアルタイムにフィルタリングすることもできるのでやってみます。

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>

<p ng-init="frameworks = ['Backbone.js', 'Ember.js', 'Knockout.js']">
    <h3>{{ frameworks.length }} frameworks</h3>
    <input type="text" ng-model="searchText" /> <!-- 検索窓を設置 -->
    <ul>
        <li ng-repeat="f in frameworks | filter:searchText"> <!-- 変数によるフィルタリング -->
            <a ng-href="/#/frameworks/{{f}}">{{f|uppercase}}</a>
        </li>
    </ul>
</p>

kobito.1386191332.955234.png

バインディングやテンプレートがなかったらかなり面倒ですが、Angularだとここまで簡単になります笑

フィルターの定義

フィルターの定義も簡単にできます。

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

angular.module('angularSampleApp', [
        'ngCookies', 'ngResource', 'ngSanitize', 'ngRoute'
    ])
    .config(function ($routeProvider) {
        $routeProvider
            .when('/', {
                templateUrl: 'views/main.html',
                controller: 'MainCtrl'
            })
            .when('/frameworks/:name', {
                templateUrl: 'views/desc.html',
                controller: 'DescCtrl'
            })
            .otherwise({
                redirectTo: '/'
            });
    })
    // フィルター `reverse` の定義
    .filter('reverse', function () {
        return function (values) {
            return values.concat().reverse();
        };
    });

.filter()にフィルター名と、 どう変換するかの処理を記述したクロージャーをreturnするクロージャー を渡せば良いです。

この例だと、ただ単に配列を逆順にするreverseフィルターです。

定義したフィルターを使ってみる

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>

<p ng-init="frameworks = ['Backbone.js', 'Ember.js', 'Knockout.js']">
    <h3>{{ frameworks.length }} frameworks</h3>
    <input type="text" ng-model="searchText" />
    <ul>
        <li ng-repeat="f in frameworks | reverse | filter:searchText"> <!-- reverseフィルタを追加 -->
            <a ng-href="/#/frameworks/{{f}}">{{f|uppercase}}</a>
        </li>
    </ul>
</p>

kobito.1386193743.862862.png

逆順になりました!
使い方はビルドインのフィルタと同じですが、フィルターがネスト可能だと言う例も兼ねてます。

frameworks|reverse|reverseとすれば元に戻ります。

次回は、AngularJS 入門 ~ サービス, DIの予定です。

75
72
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
75
72