Bootstrap与QUOT;扣子,广播QUOT;与AngularJS切换 [英] Bootstrap "buttons-radio" toggle with AngularJS

查看:254
本文介绍了Bootstrap与QUOT;扣子,广播QUOT;与AngularJS切换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了一个小角模块与引导按钮组(记者加了一些JavaScript集成,使它们像单选按钮的工作我做了这个模块上的复选框做一样的:<一HREF =htt​​p://jsfiddle.net/evaneus/z9rge/> http://jsfiddle.net/evaneus/z9rge/

我的code是在 http://jsfiddle.net/askbjoernhansen/YjMMD/

我的问题:

1)这是正确的做法?

2)的模型观看三次,还是$范围。$腕表()弄清楚,这是相同的模型,只是做一次?看起来是这样。

3)它是正确的渣土周围的$手表功能像我这样做的DOM?感觉脏,但我想这就是我要求的时候我加入角的东西,本身不是angularjs兼容。还是?

4)是否有把NG-模型属性的BTN-组,而不是对每个按钮的方法吗?这会使其出现了大量的清洁剂。

您可以在我的jsfiddle看到它上面,或code是在这里,先在html:

 &LT;! - 检验模型双向 - &GT;
  &LT;输入名称=测试类型=电台NG-模式=基于myModel ['A']VALUE =左&GT;左&LT; BR&GT;
  &LT;输入名称=测试类型=电台NG-模式=基于myModel ['A']VALUE =中间&GT;中东&LT; BR&GT;
  &LT;输入名称=测试类型=电台NG-模式=基于myModel ['A']VALUE =右&GT;右LT; BR&GT;
基于myModel A {{基于myModel ['A']}}&LT; BR /&GT;&LT; D​​IV CLASS =BTN-组数据切换=按钮无线电&GT;
  &LT;按钮式=键按钮无线电=
    NG-模式=基于myModel ['A']VALUE =左级=BTN&GT;左,LT; /按钮&GT;
  &LT;按钮式=键按钮无线电=
    NG-模式=基于myModel ['A']VALUE =中间级=BTN&GT;中&LT; /按钮&GT;
  &LT;按钮式=键按钮无线电=
    NG-模式=基于myModel ['A']VALUE =右级=BTN&GT;右&LT; /按钮&GT;
&LT; / DIV&GT;

和JavaScript:

  angular.module('buttonsRadio',[])。指令(buttonsRadio',函数(){
    返回{
        限制:'A',
        要求:'ngModel',
        链接:功能($范围,元素,属性CTRL){
            element.bind('点击',功能(){
                $范围。$应用(功能(适用范围){
                    CTRL $ setViewValue(attr.value)。
                });
            });            //这应该只是一次添加,但添加了对每个无线输入呢?
            $范围。$腕表(attr.ngModel,功能(为newValue,属性oldValue){
                。element.parent(BTN-集团)找到('按钮')removeClass移除(活动)。
                element.parent(BTN-组)
                .find(按钮[值='+ +为newValue'])addClass(激活)。
            });
        }
    };
});


解决方案

您调用的指令三次,每次一个按钮。 AFAIK这意味着联函数被调用三次,结合事件和看更改。的更增添了一点在这个下面。

它的优良改变DOM时模型改变,但你在做什么 - 改变类和值的 - 可以自动完成的角度使用双向数据绑定和原生指令,如纳克级

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

  $ scope.myOptions =左,中,右];
$ scope.myModel =左

您可以创建一个这样的按钮无线电指令

  App.directive('buttonsRadio',函数(){
    返回{
        限制:'E',
        适用范围:{模式:'=',选择:=},
        控制器:函数($范围){
            $ scope.activate =功能(选件){
                $ scope.model =选项;
            };
        },
        模板:&LT;按钮式='按钮'类='BTN'+
                    NG-CLASS ='{活跃:选项==模型}'+
                    NG重复='选项中选择'+
                    NG点击='激活(可选)'&GT; {{选项}}+
                  &LT; /按钮&gt;中
    };
});

可以从你的HTML调用

 &LT;按钮无线电类=BTN-组数据切换=按钮无线电
               模型='基于myModel
               选项​​='myOptions'&GT;
&LT; /按钮无线电&GT;

事情需要注意:


  1. 模板使用哪些相应的穿过所有的选项,并编译按钮的 NG-重复指令。

  2. 该指令有其自己的控制器和孤立的范围与模式选项来接受双向绑定,所以角做它的魔力,当指令改变他们的价值观。

  3. 如果该选项的模型的当前值相匹配,则该按钮被分配了一个有效类。

  4. 当按钮被pressed,该方法激活(从指令控制器)被调用,它改变了模型的价值。

继承人的jsfiddle http://jsfiddle.net/jaimem/A5rvg/4/


修改

我不能完全肯定这一点,但肯定的,你的车型将拥有的不同的观察者,一个用于指令每次调用。如果您正在使用 Batarang 你可以看到从的性能全部看了前pressions 的标签和 AngularJS属性的面板。 Batarang也暴露了一个 $范围的便利性,这样你就可以从控制台

运行下面查找你的模型的手表对象

  $范围$$ watchers.filter(函数(W){返回w.exp ===基于myModel ['A']});

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/

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

My questions:

1) Is this the right approach?

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.

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?

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.

You can see it at my jsfiddle above, or the code is here, first the 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:

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

解决方案

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.

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

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

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

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

Things to notice:

  1. The template uses an ng-repeat directive which goes through all options and compiles buttons accordingly.
  2. The directive has its own controller and isolated scope with model and options to 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 active class.
  4. When a button is pressed, the method activate (from the directives controller) is called, and it changes the value of the model.

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


EDIT

I wasn't completely sure about this, but yes, your model will have three different watchers, one for every directive invocation. If you are using Batarang you can see all the watched expressions from the Performance tab and the AngularJS Properties panel. Batarang also exposes an $scope convenience property, so you can look for your model's watch objects by running the following from the console

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

这篇关于Bootstrap与QUOT;扣子,广播QUOT;与AngularJS切换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆