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
Bootstrap "buttons-radio" toggle with AngularJS
提问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-radio
directive 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:
注意事项:
- The template uses an
ng-repeat
directive which goes through all options and compiles buttons accordingly. - The directive has its own controller and isolated scope with
model
andoptions
to accept bi-directional binding, so angular does its magic when the directive changes their values. - If the option matches the current value of the model, then the button is assigned an
active
class. - When a button is pressed, the method
activate
(from the directives controller) is called, and it changes the value of the model.
- 该模板使用一个
ng-repeat
指令,该指令遍历所有选项并相应地编译按钮。 - 该指令有自己的控制器和隔离范围,
model
并options
接受双向绑定,因此当指令更改其值时,angular 会发挥其魔力。 - 如果该选项与模型的当前值匹配,则为按钮分配一个
active
类。 - 当按下按钮时,
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 $scope
convenience 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>