【问题标题】:AngularJS: Radio buttons do not work with Bootstrap 3AngularJS:单选按钮不适用于 Bootstrap 3
【发布时间】:2013-10-09 16:00:47
【问题描述】:

我有一个单选按钮,它根据交易类型的值设置TrueFalse 的值

demo可以在here找到

问题是当我点击任何单选按钮时,$scope.transaction.debit 的值不会改变

我的javascript代码是

    var app = angular.module('myApp', []);

    app.controller("MainCtrl", function($scope){
      $scope.transaction = {};
      $scope.transaction.debit=undefined;

      console.log('controller initialized');
    });

请让我知道我做错了什么。

另外,我不想为此使用Angular-UIAngularStrap,除非没有其他选项可用。

【问题讨论】:

  • 你是对的。删除单选按钮周围的引导代码会使它们再次工作。我怀疑由于引导程序而实际上没有选择单选按钮?请注意,删除对 bootstrap.js 文件的脚本引用也会使它们再次工作,即使使用工作的 css
  • 您也可以寻找类似的问题(Angular-Strap Radio Button won't update model)。虽然它涉及库的冲突,主要是指bootstrap3 + angular-strap,但有人(或将来的你)可能会寻找它。

标签: javascript twitter-bootstrap angularjs angularjs-scope


【解决方案1】:

我修改了dpineda's solution。您可以在不删除 bootsrap.js 依赖项的情况下使用。还有一个工作示例here

这是流程:

  1. 删除 data-toggle="buttons" 以防止引导程序执行。
  2. 添加一些 CSS 来修复损坏的视图(btn-radio css 类)
  3. 为检查样式效果添加一些 AngularJS 逻辑。

html

<div class="btn-group col-lg-3">
  <label class="btn btn-default btn-radio" ng-class="{'active': transaction.debit == '0'}">
    <input type="radio" data-ng-model="transaction.debit" value="0"> Debit
  </label>
  <label class="btn btn-default btn-radio" ng-class="{'active': transaction.debit == '1'}">
    <input type="radio" data-ng-model="transaction.debit" value="1"> Credit
  </label>
</div>

<p>Transaction type: {{transaction.debit}}</p>

JavaScript

var app = angular.module('myApp', []);

app.controller("MainCtrl", function($scope) {

  $scope.transaction = {
    debit: 0
  };
});

风格

.btn-radio > input[type=radio] {
  position       : absolute;
  clip           : rect(0, 0, 0, 0);
  pointer-events : none;
}

【讨论】:

  • 我发现关键问题是删除 data-toggle="buttons" 以禁用 bootstrap.js 的那部分功能,然后添加上述样式以补偿实际单选按钮的重新出现。
  • 我在 Angular 6 中仍然遇到这个问题,我通过删除 data-toggle="buttons" 并将 [class.active]="option == 'value'" 添加到每个标签来解决这个问题。我不需要进行任何 CSS 更改。
【解决方案2】:

我在bootstrap.js 中发现了问题。评论e.preventDefault()这一行,它可以工作。

// BUTTON DATA-API
// ===============
$(document)
.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
    var $btn = $(e.target)
    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
    Plugin.call($btn, 'toggle')
    e.preventDefault() //Before
    //e.preventDefault() //After
})
.on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
    $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
})

【讨论】:

    【解决方案3】:

    您在单选按钮的顶部粘贴了一个大标签,该标签会阻止您输入单选按钮。 html 应为:

     <input type="radio" data-ng-model="transaction.debit" value="True">Debit</input>
    
     <input type="radio" data-ng-model="transaction.debit" value="False">Credit</input>
    

    然后它就可以工作了,当然它可能看起来不像你想要的那样。

    【讨论】:

    • 删除 bootstrap.js 文件解决了这个问题,这让我相信它与标签无关,但更多与 javascript bootstrap 注入有关。同时,删除标签当然会阻止引导 javascript 在这些对象上运行。
    • 另一种方法是在标签上使用 ng-click 来处理点击和数据交互。然后,您不必删除引导 javascript。 plnkr.co/edit/8i86U2?p=preview
    • 这个链接解释了如何使用 Bootstrap 和 Angular:scotch.io/tutorials/…
    • 即使是 Plunker 也对这个错误的 &lt;/input&gt; 结束标签进行了检查。怎么选的答案?
    【解决方案4】:

    如果您删除 de bootstrap 代码,您可以使用条件控制样式

    <label class="btn btn-default" ng-class="{'active': transaction.debit == 'some'}">
        <input type="radio" data-ng-model="transaction.debit" name="debit" value="some"> Some
    </label>
    <label class="btn btn-default" ng-class="{'active': transaction.debit == 'other'}">
        <input type="radio" data-ng-model="transaction.debit" name="debit" value="other"> Other
    </label>
    

    【讨论】:

      【解决方案5】:

      这是一个使用新指令的工作版本:

      html

      <section ng-controller="MainCtrl">
      <div class="form-group">
          <label class="col-lg-2 control-label">Type</label>
      
          <div class="btn-group col-lg-3" data-toggle="buttons">
              <label class="btn btn-default" radio-button ng-model="transaction.debit" value="True">
                  Debit
              </label>
              <label class="btn btn-default" radio-button ng-model="transaction.debit" value="False">
                  Credit
              </label>
          </div>
      
          <p>Transaction type: {{transaction.debit}}</p>
      </div>
      </section>
      

      javascript

      // Code goes here
      var app = angular.module('myApp', []);
      
      app.controller("MainCtrl", function($scope){
        $scope.transaction = {};
        $scope.transaction.debit=undefined;
      
        console.log('controller initialized');
      });
      
      app.directive("radioButton", function() {
        return {
          restrict: 'A',
          require: 'ngModel',
          link: function(scope, element, attrs, ctrl) {
            element.bind('click', function () {
              if (!element.hasClass('active')) {
                scope.$apply(function () {
                  scope.transaction.debit = attrs.value;
                });
              }
            });
          }
        };
      })
      

      【讨论】:

      • 指令太具体了。您的解决方案失去了引导功能。 .debit=undefined 什么都不做。 -1
      【解决方案6】:

      根据 francisco.preller 的回答,我编写了两个解决方案,试图使其适合通用使用,同时不丢失输入标签: html:

              <label class="btn btn-info" radiobuttonlbl>
                <input ng-model="query.gender" type="radio" value="0">male
              </label>
      

      解决方案 #1:

      .directive("radiobuttonlbl", function() {
        return {
          restrict: 'A',
          link: function(scope, element, attrs, ctrl) {
            element.bind('click', function () {
              var input_elem = angular.element(element.find('input')[0]);
              (function(o, s, v) {
                s = s.replace(/\[(\w+)\]/g, '.$1');
                s = s.replace(/^\./, '');
                var a = s.split('.').reverse();
                while(a.length>1) {
                  var k = a.pop();
                  o = o[k];
                }
                scope.$apply(function(){ o[a.pop()]=v;});
              })(scope, input_elem.attr('ng-model'), input_elem.attr('value'));
            });
          }
        };
      })
      

      解决方案 #2:

      .directive("radiobuttonlbl", function() {
        return {
          restrict: 'A',
          link: function(scope, element, attrs, ctrl) {
            element.bind('click', function () {
              var input_elem = angular.element(element.find('input')[0]);
              input_elem.prop('checked',true);
              input_elem.triggerHandler('click'); 
            });
          }
        };
      })
      

      我觉得第一个更好,因为它可以让 Angular 完成更新工作。

      【讨论】:

      • 这个答案并不理想,但却是这个页面上最好的答案。
      【解决方案7】:

      如果有人仍在寻找一种简单的方法来做到这一点(我个人很犹豫是否用指令重载我的代码),这就是我所做的:

      您可以使用标签上的ng-click 设置值。此外,请注意第一个单选项目标签上的 ng-initactive 类。这样,您可以让 bootstrap 做它的事情,而 angular 做它的事情。唯一的缺点是您不能使用 ng-model 进行角度控制。

      <div class="btn-group col-lg-3" data-toggle="buttons">
            <label class="btn btn-default active" ng-init="transaction.debit=true" ng-click="transaction.debit=true">
              <input type="radio" checked> Debit
            </label>
            <label class="btn btn-default" ng-click="transaction.debit=false">
              <input type="radio"> Credit
            </label>
          </div>
      

      【讨论】:

        【解决方案8】:

        我遇到了同样的问题。使用 ng-click 在您的标签上,它可以与引导程序一起正常工作

        <label class="btn btn-default" ng-click="transaction.debit = 'debit'">
        

        Here it's working in plunker

        【讨论】:

          【解决方案9】:

          我有同样的问题,在我的情况下,默认样式更改并且不能在任何单选或复选框按钮内使用角度 ng-model。所以我读了一些文章,发现有时如果你在 Bootstrap 之后加载 JQuery,它会覆盖 jQuery 的任何其他实例,并且它会阻止默认样式和组件作为引导组件加载,如果你在 jQuery 之后加载 angularJS 也会发生这种情况,反之亦然。

          PS.- 我的回答:检查您的加载脚本堆栈,使用它并找到适合您的顺序。 (首先是 jquery,然后是 angularJs,最后是 bootstrap)。通常你需要 jQuery 作为第一选择,Angular 和几乎每个新框架都在它之上工作。干杯。

          【讨论】:

          • 完美。这就是问题所在。我在 jquery.min.js 之前加载了 bootstrap.min.js,问题完全消失了!谢谢。
          • 不幸的是,这解决了这个特定问题但破坏了其他一切,因为 jQuery 是 Bootstrap 的依赖项
          猜你喜欢
          • 1970-01-01
          • 2013-08-02
          • 2013-09-06
          • 2013-02-18
          • 2014-02-27
          • 1970-01-01
          • 1970-01-01
          • 2016-10-13
          • 2018-07-28
          相关资源
          最近更新 更多