CodeZine(コードジン)

特集ページ一覧

AngularJSとBootstrapを組み合わせてUIコンポーネントを作ってみよう

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

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2015/09/18 14:00

ダウンロード AngularJS_Part12.zip (517.4 KB)

目次

入力コンポーネントを作ってみる(2)

ngModelと連携した実装

 続いて、ngModelと連動するようそれぞれの中身を実装していきます。buttonGroupディレクティブで使用されるButtonGroupControllerの中身はリスト7のようになります。

リスト7 ButtonGroupControllerの実装例(js/directives/ButtonGroup.jsの抜粋)
function ButtonGroupController($scope){
    var items = [];
    //(1)選択(クリック)されたボタンのスタイルを変更する
    function select(value){
        for(var i = 0; i < items.length; i++){
            var $_scope = items[i];
            if($_scope.value == value){
                $_scope.active = true;
            }
            else{
                $_scope.active = false;
            }
        }
    }
    //(2)buttonItemの$scopeを追加するメソッド
    this.addItem = function($_scope){
        items.push($_scope);
    };
    //(3)外部からの変更を受け付けるメソッド
    this.setValue = function(val){
        select(val);
    };
    //(4)コンポーネント内での変更を受け付けるメソッド
    this.select = function($_scope){
        select($_scope.value);
        //(5)変更時にはイベントでディレクティブへ値を通知する
        $scope.$emit('change',$_scope.value);
    }
}

 (1)ではボタンがクリックされた時にアクティブな要素の指定を行う共通関数を定義しています。また、(2)では子のbuttonItemディレクティブ(スコープ)を把握できるようにメソッドを作成します。このメソッドは、buttonItemディレクティブでのlinkメソッドから利用します。

 続いて(3)ではコンポーネント外で値が変わったときに、その値を反映させるためのメソッドです。そして、最後にコンポーネントでの値の変更、つまり、ボタンをクリックしたときに実行されるメソッドが(4)のようになります。

 (3)と同様にボタンをアクティブな値の設定を行いつつ、(5)のように変更のタイミングでイベントは発火するようにしています。これは、スコープを共有するbuttonGroupに変更を通知するためです。

 続いて、buttonItemのlinkメソッドはリスト8のように実装します。

リスト8 buttonItemディレクティブのリンクメソッドの実装例 (js/directives/ButtonGroup.jsの抜粋)
//(1)buttonGroupControllerの利用
var link = function($scope,$element,$attrs,buttonGroupController){
    //(2)buttonGroupControllerへ追加
    buttonGroupController.addItem($scope);
    //(3)要素を選択した時の処理
    $element.click(function(){
        buttonGroupController.select($scope);
    });
};

 (1)ではlinkメソッドの第4引数でbuttonGroupControllerのインスタンスを取得しています。そして、(2)では先ほど作成したaddItemメソッドで要素オブジェクトの$elementを登録することと、その要素がクリックされた時に(3)のようにselectメソッドを呼びます。

 ここまでできれば、見た目の部分の作成は完成したといえます。

 続いて、ngModelとの連携をするために、buttonGroupディレクティブのlinkメソッドをリスト9のように実装します。

リスト9 ButtonGroupディレクティブのリンクメソッドの実装例 (js/directives/ButtonGroup.jsの抜粋)
var link = function($scope,$element,$attrs,controllers){
    //(1)requireで指定した順番でcontrollerが配列で取得可能
    var buttonGroupController = controllers[0];
    var ngModelController = controllers[1];
    //(2)ngModelの値が外部より変更されたときによばれるメソッドの定義
    ngModelController.$render = function(){
        buttonGroupController.setValue(ngModelController.$viewValue);
    };
    //(3)値が変わったときにngModelで双方向バインディングされている変数への値の設定
    $scope.$on('change',function(evt,val){
        ngModelController.$setViewValue(val);
    });
};

 buttonGroupディレクティブのrequire属性では、配列を用いて依存を指定したため、linkメソッドの第4引数のコントローラも配列でわたってきます。従って、(1)のようにコントローラを取得する際には順番に気をつけて取得する必要があります。

 (2)では、外部から値を変更されたときの処理で、NgModelControllerでは値の変更時には$renderメソッドが呼ばれますのでその処理を定義します。また、コンポーネントから値が変更されたときは(3)のように$setViewValueメソッドで値を変更します。その他、ここで使っている関数や変数の意味を知るにはNgModelControllerのリファレンスを参照して下さい。

もっと便利なコンポーネントにするために

 ngModelを使えばformディレクティブと連携して機能することができます。ただし、これまでの実装だけではformディレクティブを使う際に有効なバリデーションが機能していません。

 サンプルコードでは実際にformディレクティブとバリデーション部分で連携するように追加のコードがあります。

 これらのサンプルコードを参考に、より便利なコンポーネントに自分好みのカスタマイズをしていただければと思います。

最後に

 実はBootstrapとAngularJSを連携したライブラリはUI Bootstrapというものが既に存在します。従って、早急にBootstrapを組み込みたいならこのライブラリを使えばよいのですが、汎用的に作られているので指定できるオプションも非常に多岐にわたり、Bootstrapを知らないと使いにくいところがあります。実際のプロジェクトなどでは用途も定まっているために、もっと簡略化するためや、ng-includeなどの代わりにカスタムディレクティブを使えば、さらに効率のよい開発ができるのではないかと思います。

参考資料



  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

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

もっと読む

著者プロフィール

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

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。個人紹介主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしど...

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

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5