【问题标题】:Conditionally add the "multiple" attribute to ui-select有条件地将“multiple”属性添加到 ui-select
【发布时间】:2015-10-30 13:46:31
【问题描述】:

我正在尝试根据使用ng-attr- 指令的某个属性的值将multiple 属性添加到ui-select 指令。不幸的是,这对我不起作用。我已经设置了一个 plunker 示例来展示正在发生的事情。

Plunker Example

【问题讨论】:

    标签: javascript angularjs angularjs-directive ui-select


    【解决方案1】:

    编辑

    在阅读了 Angular Repo 中提到的GitHub Issue 后,我终于明白了。

    您需要设置一个具有更高priorityterminal 属性设置为true 的指令(在我们的指令编译后跳过所有其他指令的编译)。 然后在postLink 函数中,我们将编译整个元素本身。但在此之前,我们自己的指令需要被移除(无限循环!)。

    Add directives from directive in AngularJS的大手笔

    指令代码

    angular.module('app')
      .directive('multiSelectChecker', function ($compile) {
        return {
          restrict: 'A',
          replace: false, 
          terminal: true, //terminal means: compile this directive only
          priority: 50000, //priority means: the higher the priority, the "firster" the directive will be compiled
          compile: function compile(element, attrs) {
            element.removeAttr("multi-select-checker"); //remove the attribute to avoid indefinite loop
            element.removeAttr("data-multi-select-checker"); //also remove the same attribute with data- prefix in case users specify data-multi-select-checker in the html
    
            return {
              pre: function preLink(scope, iElement, iAttrs, controller) {  },
              post: function postLink(scope, iElement, iAttrs, controller) { 
                if(scope.options.Multiple == true) {
                  iElement[0].setAttribute('multiple',''); //set the multiple directive, doing it the JS way, not jqLite way.
                }
                $compile(iElement)(scope);
              }
            };
          }
        };
      });
    

    HTML 代码

      <ui-select ng-model="model.choice" multi-select-checker>
        <ui-select-match>{{$item.Title}}</ui-select-match>
        <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
          <div ng-bind="item.Title | highlight: $select.search"></div>
        </ui-select-choices>
      </ui-select>
    

    工作计划:

    http://plnkr.co/edit/N11hjOFaEkFUoIyeWqzc?p=preview


    原始答案(同样有效,但代码重复)

    我做了以下事情:

    1. 创建了一个名为 multi-select-checker 的包装指令
    2. 在该指令中检查 options.Multiple 是真还是假
    3. 为每个案例返回两个不同的模板 URL。案例 1):返回 single-select.tpl.html 或案例 2):返回 mutli-select.tpl.html(其中包括 'multiple' 指令。

    指令代码:

    app.directive('multiSelectChecker', function() {
    return {
        template: '<ng-include src="getTemplateUrl()"/>',
        controller: function($scope) {
          $scope.getTemplateUrl = function() {
            if($scope.options.Multiple == true) {
              console.log("multi-select");
              return "multi-select.tpl.html"
            }
            else {
              console.log("single select");
              return "single-select.tpl.html"
            }
          }
        }
      }
    })
    

    在 HTML 中的用法:

    <body ng-controller="DemoCtrl">
      <multi-select-checker>
      </multi-select-checker>
    </body>
    

    模板一:单选

    <ui-select ng-model="model.choice">
        <ui-select-match>{{$item.Title}}</ui-select-match>
        <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
            <div ng-bind="item.Title | highlight: $select.search"></div>
        </ui-select-choices>
    </ui-select>
    

    模板 2:多选

    <ui-select ng-model="model.choice" multiple>
        <ui-select-match>{{$item.Title}}</ui-select-match>
        <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
            <div ng-bind="item.Title | highlight: $select.search"></div>
        </ui-select-choices>
    </ui-select>
    

    如您所见,这两个模板只有一个指令不同:'multiple'。也许有更好的解决方案。

    我什至不明白,为什么 ng-attr-multiple 方法不起作用。

    此外,我已经意识到,有两个单独的输入字段通过 ng-attr-multiple 方法呈现。

    而且单选案例似乎被打破了(通过删除多个指令) - 这也在你最初的 Plnkr 中。

    工作代码

    在此处查看正在运行的 Plnkr:http://plnkr.co/edit/T9e5tcAkcQLsDV3plfEl?p=preview

    【讨论】:

    • 这是一个正确的解决方案,但我想避免重复代码,这就是我首先尝试使用ng-attr 的原因。无论如何谢谢:)
    • 您可以嵌入您的ui-select 的孩子 -> 这会减少您的重复代码。
    • 我已经进一步调查:似乎 ng-attr-multiple 没有评估(它的内容仍然是“{{options.Multiple}}”。我检查了 ui-select 代码,它检查是否设置了 multipe 属性 - 对于 ng-attr-multiple="{{options.Multiple}}" 甚至设置 ng-attr-multiple="" 都将评估为 true (因为它只是检查如果多重属性被定义 LoC https://github.com/angular-ui/ui-select/blob/master/src/uiSelectDirective.js#L21 - 因此被呈现为多选。
    • 更多关于您想要实现的目标的信息:github.com/angular/angular.js/issues/5524
    • 关于您的最终解决方案,如果有人想从控制器传递一个变量(不使用 $scope),您需要创建一个隔离范围,然后编译 $parent。谢谢!
    【解决方案2】:

    这是你想要达到的目标吗:

    <body ng-controller="DemoCtrl">
        This works perfectly well:
        <ui-select ng-model="model.choice" multiple>
            <ui-select-match>{{$item.Title}}</ui-select-match>
            <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
                <div ng-bind="item.Title | highlight: $select.search"></div>
            </ui-select-choices>
        </ui-select>
        <br />
        <br />
        This does not work:
        <ui-select ng-model="model.choice2" multiple="{{options.Multiple}}">
            <ui-select-match>{{$item.Title}}</ui-select-match>
            <ui-select-choices repeat="item.Id as item in options.SuggestedValues | filter: { Title: $select.search }">
                <div ng-bind="item.Title | highlight: $select.search"></div>
            </ui-select-choices>
        </ui-select>
      </body>
    

    【讨论】:

    • 是的,但它不起作用。因为无论 options.Multiple 的值是什么,它总是被假定为一个多选选择。
    • 是的,我现在明白了。似乎这是一个未解决的问题,请查看github.com/angular/angular.js/issues/7714 和 Narretz 的回答:“目前不支持绑定到多个。它被禁止,因为它会导致 select 指令出现问题。”
    • 是的,我使用 ng-attr 指令让它工作,但它失败了。它确实添加了 multiple 属性,但它搞砸了 ui-select-match 嵌套指令:显然,它在添加 multiple 属性之前被编译,因此它的行为就像在单选 ui-select 的上下文中一样。任何想法如何解决这个问题?
    • 对不起,伙计,我不知道如何解决这个问题。框架不支持。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    • 2023-04-05
    • 2016-09-26
    相关资源
    最近更新 更多