如何修改AngularJS Bootstrap下拉/选择以使其不使用jQuery?

时间:2015-01-20 16:57:20

标签: angularjs angular-ui-bootstrap

我看到一个非常好的AngularJS Bootstrap类型的Select指令示例:

http://jsfiddle.net/cojahmetov/3DS49/

这满足了我的大多数需求,但它使用jQuery而我们没有使用该库。

本例中使用的jQuery非常小,但我不知道如何替换看起来像这样的元素定位器:

任何人都可以给我任何关于如何替换它的指示:

switch (attrs.menuType) {
  case "button":
    $('button.button-label', element).html(item.name);
    break;
  default:
    $('a.dropdown-toggle', element).html('<b class="caret"></b> ' + item.name);
    break;
}

这样它可以在没有jQuery的情况下工作吗?理想情况下,我希望有人知道可能会提出基于ui-bootstrap版本的版本。也许这甚至可能会被添加到ui-bootstrap以供其他人使用。

3 个答案:

答案 0 :(得分:14)

小提琴的想法很不错,但我发现实施有点混乱。那么一个人能做什么呢?好吧,当然,在dropdown之上写一个替代的ui-bootstrap指令!

希望您觉得这很有帮助。它应该非常容易使用。

<强>用法

<dropdown is-button 
          ng-model="vm.item" 
          items="vm.items" 
          callback="vm.callback(item)">
</dropdown>

所以你传入保留初始选择的ng-model,如果有的话。从指令设置新值。在items中,您可以选择id-name对的集合,如果需要,可以选择callback。如果您指定is-button属性,则会获得按钮时尚的下拉控件。

然后控制器可能如下所示。

<强>控制器

// Controller
app.controller('Ctrl', function() {
  var vm = this;

  // items collection
  vm.items = [{
      id: 0,
      name: 'London'
    },{
      id: 1,
      name: 'Paris'
    },{
      id: 2,
      name: 'Milan'
    }];

  // current item
  vm.item = null; // vm.items[1];

  // directive callback function    
  vm.callback = function(item) {
    vm.fromCallback = 'User selected ' + angular.toJson(item);
  };
});

dropdown指令的逻辑非常简单,真的。

指令javaScript

// Dropdown directive 
app.directive('dropdown', function() {
  return {
    restrict: 'E',
    require: '^ngModel',
    scope: {
      ngModel: '=', // selection
      items: '=',   // items to select from
      callback: '&' // callback
    },
    link: function(scope, element, attrs) {
      element.on('click', function(event) {
        event.preventDefault();
      });

      scope.default = 'Please select item';
      scope.isButton = 'isButton' in attrs;

      // selection changed handler
      scope.select = function(item) {
        scope.ngModel = item;
        if (scope.callback) {
          scope.callback({ item: item });
        }
      };
    },
    templateUrl: 'dropdown-template.html'
  };
});

指令HTML模板

<div class="btn-group" dropdown>

  <!-- button style dropdown -->
  <button ng-if="isButton" 
          type="button" 
          class="btn btn-primary"
          ng-bind="ngModel.name || default">
  </button>
  <button ng-if="isButton" 
          type="button" 
          class="btn btn-primary dropdown-toggle" 
          dropdown-toggle>
    <span class="caret"></span>
  </button>

  <!-- no button, plz -->
  <a ng-if="!isButton" 
     class="dropdown-toggle"
     dropdown-toggle href
     ng-bind="ngModel.name || default">
  </a>
  <span ng-if="!isButton" class="caret"></span>

  <!-- dropdown items -->
  <ul class="dropdown-menu" role="menu"> 
    <li ng-repeat="item in items">
      <a href="#" 
         ng-bind="item.name" 
         ng-click="select(item)"></a>
    </li> 
  </ul>

</div>

这是外观&amp;感觉初步实施。除了您提供的示例之外,您还将获得整个对象,而不仅仅是id

enter image description here

<小时/> 相关的Plunker http://plnkr.co/edit/bLWabx使用angularjs 1.4.0-beta.3和ui-bootstrap 0.12.0。

答案 1 :(得分:3)

此解决方案仅支持IE9 +,如果您需要支持旧版浏览器,我可以找到其他解决方案并进行更新。

http://jsfiddle.net/3DS49/160/

scope.selectVal = function (item) {
    function selector(sel, htmlCont)
    {
        var elems = document.querySelectorAll(sel);
        Array.prototype.forEach.call(elems, function(el, i){
            el.innerHTML = htmlCont;
        });
    }
    switch (attrs.menuType) {
        case "button":
            selector('button.button-label', item.name);
            break;
        default:
            selector('a.dropdown-toggle', '<b class="caret"></b> ' + item.name);
            break;
    }
    scope.doSelect({
        selectedVal: item.id
    });
};

答案 2 :(得分:2)

编辑:我是对的,你不需要在这个例子中使用.html(),一般来说这是一个不好的做法。请注意我如何使用scope对象来完成相同的结果:http://jsfiddle.net/3DS49/162/

对于您在此处显示的最小示例,您可以使用angular.element代替$jQueryangular.element是一个子集,但它支持.html()。

然而,这仍然是一个不好的做法,因为内容可以放在scope中,html内容可以设置为按钮模板中的直接绑定。

编辑:angular.element不支持选择器。您应该使用本机方法(getElementById及其朋友)。但是,请确保您不使用特定于jquery的选择器,例如:first。 E.g:

var elements = document.querySelectorAll(".myclass");

//it is up to you to iterate over the elements and call angular.element(element).html(yourValueHere) on each element.

//NOTE: you can get document from $windowProvider.$get().document, or $window.document, depending on the place (you will use $window.document in this case).

修改:检查浏览器支持here - 没有支持选择器的本地角度方式。

对于特定案例的实际实施,可以安全地看到@ChrisFrank的答案。但是,请记住,您可以使用angular.element函数包装迭代的每个元素(例如在他的答案中)以获取jqLit​​e(AngularJS构建在jQuery的子集中 - 您不需要任何其他库)对象。