小さな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');
});
}
};
});
このディレクティブは、ボタンごとに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>
注目すべきこと:
ng-repeat
ディレクティブを使用して、すべてのオプションを実行し、それに応じてボタンをコンパイルします。model
とoptions
で分離されたスコープを持ち、双方向バインディングを受け入れるため、angularはディレクティブが値を変更するときに魔法をかけます。active
クラスが割り当てられます。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']"});
これは簡単です
<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>