I'm trying to add the multiple
attribute to a ui-select
directive based on the value of a certain property using the ng-attr-
directive. Unfortunately, that's not working for me. I've setup a plunker example to showcase what is happening.
Plunker Example
Edit
I finally got it after reading through the mentioned GitHub Issue in the Angular Repo.
You need to set up a directive with a higher priority
and a terminal
attribute set to true (which skips the compilation of all other directives, after the compilation of our directive).
Then in the postLink
function we will compile the whole element itself. But before that our own directive needs to be removed (infinite loop!).
Big shot outs to Add directives from directive in AngularJS
Directive Code
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 Code
<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>
Working Plnkr:
http://plnkr.co/edit/N11hjOFaEkFUoIyeWqzc?p=preview
Original answer (also working, but with duplicate code)
I did the following:
- Created a wrapping directive called
multi-select-checker
- In that directive check wether the
options.Multiple
is true or false
- Return two different template URLs for each case. Case 1): return single-select.tpl.html or Case 2): return mutli-select.tpl.html (which includes the 'multiple' directive.
Directive code:
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"
}
}
}
}
})
Usage in HTML:
<body ng-controller="DemoCtrl">
<multi-select-checker>
</multi-select-checker>
</body>
Template 1: single select
<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>
Template 2: multi-select
<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>
As you can see the two templates only differ by one single directive: 'multiple'. Maybe there are better solutions.
I even can't understand, why the ng-attr-multiple approach isn't working.
In addition I have realized, that there are two seperate input fields being rendered via the ng-attr-multiple approach.
And the single selection case seems to be broken (by removing the multiple directive) - which was in your intial Plnkr as well.
Working Code
See the working Plnkr here: http://plnkr.co/edit/T9e5tcAkcQLsDV3plfEl?p=preview
Is this what you want to achieve:
<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>