19

我制作了一个小的角度模块来与引导程序“按钮组”(加上一些 javascript 以使它们像单选按钮一样工作。我在这个模块上做了同样的复选框:http://jsfiddle .net/evaneus/z9rge/

我的代码在http://jsfiddle.net/askbjoernhansen/YjMMD/

我的问题:

1)这是正确的方法吗?

2) 模型会被观看 3 次,还是 $scope.$watch() 会发现它是同一个模型而只观看一次?好像是这样的。

3) 像我一样在 $watch 函数中处理 DOM 是否“正确”?感觉“脏”,但我想这就是我在将 angular 添加到与 angularjs 本身不兼容的东西时所要求的。或者?

4)有没有办法将 ng-model 属性放在 btn-group 而不是每个按钮上?那会让它看起来更干净。

你可以在我上面的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');
            });
        }
    };
});​
4

2 回答 2

26

您正在调用该指令三次,每个按钮一次。AFAIK 这意味着链接函数被调用了三次,绑定事件并观察变化。在下面添加了更多内容。

模型更改时更改 DOM 很好,但是您正在做的事情 -更改类和值- 可以通过 Angular 使用双向数据绑定和本机指令自动完成,例如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接受双向绑定,因此当指令更改其值时,角度会发挥其魔力。
  3. 如果选项与模型的当前值匹配,则为按钮分配一个active类。
  4. 当一个按钮被按下时,方法activate(来自指令控制器)被调用,它改变了模型的值。

这是一个 JSFiddle http://jsfiddle.net/jaimem/A5rvg/4/


编辑

我对此并不完全确定,但是是的,您的模型将有三个不同的观察者,每个指令调用一个。如果您使用Batarang ,您可以从Performance选项卡和AngularJS 属性面板中查看所有观察到的表达式。Batarang 还公开了一个$scope便利属性,因此您可以通过从控制台运行以下命令来查找模型的手表对象

$scope.$$watchers.filter(function(w){return w.exp ==="myModel['A']"}); 
于 2012-11-19T08:56:31.613 回答
7

这很简单

<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>
于 2014-08-14T13:57:05.003 回答