SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

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

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

ダウンロード 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などの代わりにカスタムディレクティブを使えば、さらに効率のよい開発ができるのではないかと思います。

参考資料

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
AngularJSではじめるJavaScriptフレームワーク開発スタイル連載記事一覧

もっと読む

この記事の著者

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

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

WINGSプロジェクト について> 有限会社 WINGSプロジェクト が運営する、テクニカル執筆コミュニティ(代表 ...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/8927 2015/09/18 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー