有条件地将“multiple”属性添加到 ui-select
Posted
技术标签:
【中文标题】有条件地将“multiple”属性添加到 ui-select【英文标题】:Conditionally add the "multiple" attribute to ui-select 【发布时间】:2015-10-30 13:46:31 【问题描述】:我正在尝试根据使用ng-attr-
指令的某个属性的值将multiple
属性添加到ui-select
指令。不幸的是,这对我不起作用。我已经设置了一个 plunker 示例来展示正在发生的事情。
Plunker Example
【问题讨论】:
【参考方案1】:编辑
在阅读了 Angular Repo 中提到的GitHub Issue 后,我终于明白了。
您需要设置一个具有更高priority
和terminal
属性设置为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
原始答案(同样有效,但代码重复)
我做了以下事情:
-
创建了一个名为
multi-select-checker
的包装指令
在该指令中检查 options.Multiple
是真还是假
为每个案例返回两个不同的模板 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 的上下文中一样。任何想法如何解决这个问题? 对不起,伙计,我不知道如何解决这个问题。框架不支持。以上是关于有条件地将“multiple”属性添加到 ui-select的主要内容,如果未能解决你的问题,请参考以下文章