jQuery Bootstrap“buttons-radio”切换与 AngularJS

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13448455/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 12:37:59  来源:igfitidea点击:

Bootstrap "buttons-radio" toggle with AngularJS

jquerytwitter-bootstrapangularjs

提问by Ask Bj?rn Hansen

I made a small angular module to integrate with the bootstrap "buttons-group" ('s plus a bit of javascript to make them work like radio buttons. I made it on this module to do the same for checkboxes: http://jsfiddle.net/evaneus/z9rge/

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

My code is at http://jsfiddle.net/askbjoernhansen/YjMMD/

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

My questions:

我的问题:

1) Is this the right approach?

1)这是正确的方法吗?

2) Will the model be watched three times, or does $scope.$watch() figure out that it's the same model and just do it once? It seems that way.

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

3) Is it "correct" to muck around with the DOM in the $watch function like I do? It feels "dirty", but I guess that's what I am asking for when I am adding angular to something that's not angularjs compatible natively. Or?

3)像我一样在 $watch 函数中使用 DOM 是“正确的”吗?感觉“很脏”,但我想这就是我在向本地不兼容 angularjs 的内容中添加 angular 时所要求的。或者?

4) Is there a way to put the ng-model attribute on the btn-group instead of on each button? That'd make it appear a lot cleaner.

4) 有没有办法将 ng-model 属性放在 btn-group 而不是每个按钮上?这样会显得干净很多。

You can see it at my jsfiddle above, or the code is here, first the html:

你可以在我上面的 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>

And the javascript:

和 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');
            });
        }
    };
});?

回答by jaime

You are invoking the directive three times, once for each button. AFAIK this means the linking function is called three times, binding events and watching for changes. added a little more on this below.

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

It's fine to change the DOM when models change, but what you are doing - changing classes and values- can be done automatically by angular using bi-directional data-binding and native directives such as ng-class

当模型改变时改变 DOM 很好,但是你正在做的 -改变类和值- 可以使用双向数据绑定和本机指令通过 angular 自动完成,例如ng-class

You can create a directive that renders buttons given a list of options. For example if you have this model and these options

您可以创建一个指令来呈现给定选项列表的按钮。例如,如果你有这个模型和这些选项

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

You can create a buttons-radiodirective like this

您可以创建这样的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>"
    };
});?

which can be invoked from your HTML

可以从您的 HTML 中调用

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

Things to notice:

注意事项:

  1. The template uses an ng-repeatdirective which goes through all options and compiles buttons accordingly.
  2. The directive has its own controller and isolated scope with modeland optionsto accept bi-directional binding, so angular does its magic when the directive changes their values.
  3. If the option matches the current value of the model, then the button is assigned an activeclass.
  4. When a button is pressed, the method activate(from the directives controller) is called, and it changes the value of the model.
  1. 该模板使用一个ng-repeat指令,该指令遍历所有选项并相应地编译按钮。
  2. 该指令有自己的控制器和隔离范围,modeloptions接受双向绑定,因此当指令更改其值时,angular 会发挥其魔力。
  3. 如果该选项与模型的当前值匹配,则为按钮分配一个active类。
  4. 当按下按钮时,activate调用该方法(来自指令控制器),并更改模型的值。

Heres a JSFiddle http://jsfiddle.net/jaimem/A5rvg/4/

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



EDIT

编辑

I wasn't completely sure about this, but yes, your model will have threedifferent watchers, one for every directive invocation. If you are using Batarangyou can see all the watched expressions from the Performancetab and the AngularJS Propertiespanel. Batarang also exposes an $scopeconvenience property, so you can look for your model's watch objects by running the following from the console

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

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

回答by boneyao

this is simple

这很简单

<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>