web-dev-qa-db-ja.com

Bootstrap "buttons-radio" toggle with AngularJS

小さなangularモジュールをbootstrap "buttons-group"に統合するために作成しました(さらに、ラジオボタンのように機能させるためのJavaScriptを少し追加しました)。このモジュールでチェックボックスに対して同じことを行うようにしました: http://jsfiddle.net/evaneus/z9rge/

私のコードは http://jsfiddle.net/askbjoernhansen/YjMMD/ にあります

私の質問:

1)これは正しいアプローチですか?

2)モデルは3回監視されますか、それとも$ scope。$ watch()は同じモデルであることを認識して1回だけ実行しますか?そのようです。

3)$ watch関数でDOMをいじくり回すのは "正しい"ですか? 「汚い」と感じますが、本来、angularjsと互換性のないものにangularを追加するときに私が求めているのはそれだと思います。

4)各ボタンではなくbtn-groupにng-model属性を配置する方法はありますか?それはそれがよりきれいに見えるようになります。

あなたは上の私のjsfiddleでそれを見ることができます、またはコードはここにあります、最初にhtml:

 <!-- to test the two-way model -->
  <input name="test" type="radio" ng-model="myModel['A']" value="left"> Left<br>
  <input name="test" type="radio" ng-model="myModel['A']" value="middle"> Middle<br>
  <input name="test" type="radio" ng-model="myModel['A']" value="right"> Right<br>


myModel A {{myModel['A']}}<br/>

<div class="btn-group" data-toggle="buttons-radio">
  <button type="button" buttons-radio=""
    ng-model="myModel['A']" value="left"   class="btn">Left</button>
  <button type="button" buttons-radio=""
    ng-model="myModel['A']" value="middle" class="btn">Middle</button>
  <button type="button" buttons-radio=""
    ng-model="myModel['A']" value="right"  class="btn">Right</button>
</div>

そしてjavascript:

angular.module('buttonsRadio', []).directive('buttonsRadio', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function($scope, element, attr, ctrl) {
            element.bind('click', function() {
                $scope.$apply(function(scope) {
                    ctrl.$setViewValue(attr.value);
                });
            });

            // This should just be added once, but is added for each radio input now?
            $scope.$watch(attr.ngModel, function(newValue, oldValue) {
                element.parent(".btn-group").find('button').removeClass("active");
                element.parent(".btn-group")
                .find("button[value='" + newValue + "']").addClass('active');
            });
        }
    };
});​
19

このディレクティブは、ボタンごとに1回ずつ、3回呼び出しています。これは、リンク機能が3回呼び出され、イベントをバインドして変更を監視することを意味します。 これについて以下に少し追加しました。

モデルが変更されたときにDOMを変更することは問題ありませんが、あなたがやっていること-クラスと値の変更-angular biを使用して自動的に行うことができます方向データバインディングおよびng-classなどのネイティブディレクティブ

オプションのリストを指定してボタンをレンダリングするディレクティブを作成できます。たとえば、このモデルとこれらのオプションがある場合

$scope.myOptions = ["Left", "Middle", "Right"];
$scope.myModel = "Left"

このようなbuttons-radioディレクティブを作成できます

App.directive('buttonsRadio', function() {
    return {
        restrict: 'E',
        scope: { model: '=', options:'='},
        controller: function($scope){
            $scope.activate = function(option){
                $scope.model = option;
            };      
        },
        template: "<button type='button' class='btn' "+
                    "ng-class='{active: option == model}'"+
                    "ng-repeat='option in options' "+
                    "ng-click='activate(option)'>{{option}} "+
                  "</button>"
    };
});​

あなたのHTMLから呼び出すことができます

<buttons-radio class="btn-group" data-toggle="buttons-radio" 
               model='myModel'    
               options='myOptions'>
</buttons-radio>

注目すべきこと:

  1. テンプレートはng-repeatディレクティブを使用して、すべてのオプションを実行し、それに応じてボタンをコンパイルします。
  2. ディレクティブは独自のコントローラとmodeloptionsで分離されたスコープを持ち、双方向バインディングを受け入れるため、angularはディレクティブが値を変更するときに魔法をかけます。
  3. オプションがモデルの現在の値と一致する場合、ボタンにはactiveクラスが割り当てられます。
  4. ボタンを押すと、メソッドactivate(ディレクティブコントローラーから)が呼び出され、モデルの値が変更されます。

ここにJSFiddle http://jsfiddle.net/jaimem/A5rvg/4/


[〜#〜]編集[〜#〜]

これについては完全には分かりませんでしたが、はい、モデルには3つの異なるウォッチャーがあり、ディレクティブの呼び出しごとに1つです。 Batarang を使用している場合、PerformanceタブとAngularJSプロパティパネル。 Batarangは$scope簡易プロパティも公開しているため、コンソールから次のコマンドを実行して、モデルの監視オブジェクトを探すことができます

$scope.$$watchers.filter(function(w){return w.exp ==="myModel['A']"}); 
26
jaime

これは簡単です

<html>
    <div class="btn-group" data-toggle="buttons">
      <span class="btn btn-primary" ng-click="worktype=1" ng-class="worktype==1?'active':''">
        <input type="radio"   value="1">全职
      </span>
      <span class="btn btn-primary" ng-click="worktype=2" ng-class="worktype==2?'active':''">
        <input type="radio"   value="2">兼职
      </span>
    </div>
</html>
7
boneyao