Skip to content

Commit 3ad084f

Browse files
committedMay 25, 2016
feat(removeSelected): Implement removeSelected property for multiple selects
Implement remove-selected="false" for multiple selects. This will disable a choice in the dropdown of a multiple-select element instead of removing it.
1 parent 9d29307 commit 3ad084f

7 files changed

+82
-7
lines changed
 

‎docs/assets/demo.js

+1
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ app.controller('DemoCtrl', function ($scope, $http, $timeout, $interval) {
175175
vm.multipleDemo.selectedPeople2 = vm.multipleDemo.selectedPeople;
176176
vm.multipleDemo.selectedPeopleWithGroupBy = [vm.people[8], vm.people[6]];
177177
vm.multipleDemo.selectedPeopleSimple = ['samantha@email.com','wladimir@email.com'];
178+
vm.multipleDemo.removeSelectIsFalse = [vm.people[2], vm.people[0]];
178179

179180
vm.appendToBodyDemo = {
180181
remainingToggleTime: 0,

‎docs/examples/demo-multiple-selection.html

+14
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,18 @@ <h3>Array of objects (with groupBy)</h3>
7272
</ui-select>
7373
<p>Selected: {{multipleDemo.selectedPeopleWithGroupBy}}</p>
7474

75+
<hr>
76+
<h3>Disabling instead of removing selected items</h3>
77+
<ui-select multiple ng-model="ctrl.multipleDemo.removeSelectIsFalse" theme="bootstrap" ng-disabled="ctrl.disabled" close-on-select="false" style="width: 800px;" title="Choose a person" remove-selected="false">
78+
<ui-select-match placeholder="Select person...">{{$item.name}} &lt;{{$item.email}}&gt;</ui-select-match>
79+
<ui-select-choices repeat="person in ctrl.people | propsFilter: {name: $select.search, age: $select.search}">
80+
<div ng-bind-html="person.name | highlight: $select.search"></div>
81+
<small>
82+
email: {{person.email}}
83+
age: <span ng-bind-html="''+person.age | highlight: $select.search"></span>
84+
</small>
85+
</ui-select-choices>
86+
</ui-select>
87+
<p>Selected: {{multipleDemo.removeSelectIsFalse}}</p>
88+
7589
<div style="height:500px"></div>

‎src/common.js

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ var uis = angular.module('ui.select', [])
101101
closeOnSelect: true,
102102
skipFocusser: false,
103103
dropdownPosition: 'auto',
104+
removeSelected: true,
104105
generateId: function() {
105106
return latestId++;
106107
},

‎src/uiSelectController.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ uis.controller('uiSelectCtrl',
1818
ctrl.refreshDelay = uiSelectConfig.refreshDelay;
1919
ctrl.paste = uiSelectConfig.paste;
2020

21-
ctrl.removeSelected = false; //If selected item(s) should be removed from dropdown list
21+
ctrl.removeSelected = uiSelectConfig.removeSelected; //If selected item(s) should be removed from dropdown list
2222
ctrl.closeOnSelect = true; //Initialized inside uiSelect directive link function
2323
ctrl.skipFocusser = false; //Set to true to avoid returning focus to ctrl when item is selected
2424
ctrl.search = EMPTY_SEARCH;
@@ -240,9 +240,9 @@ uis.controller('uiSelectCtrl',
240240
}else{
241241
if ( data !== undefined ) {
242242
var filteredItems = data.filter(function(i) {
243-
return selectedItems.every(function(selectedItem) {
243+
return angular.isArray(selectedItems) ? selectedItems.every(function(selectedItem) {
244244
return !angular.equals(i, selectedItem);
245-
});
245+
}) : !angular.equals(i, selectedItems);
246246
});
247247
ctrl.setItemsFn(filteredItems);
248248
}
@@ -317,6 +317,11 @@ uis.controller('uiSelectCtrl',
317317
return isActive;
318318
};
319319

320+
var _isItemSelected = function (item) {
321+
return (ctrl.selected && angular.isArray(ctrl.selected) &&
322+
ctrl.selected.filter(function (selection) { return angular.equals(selection, item); }).length > 0);
323+
};
324+
320325
ctrl.isDisabled = function(itemScope) {
321326

322327
if (!ctrl.open) return;
@@ -325,9 +330,9 @@ uis.controller('uiSelectCtrl',
325330
var isDisabled = false;
326331
var item;
327332

328-
if (itemIndex >= 0 && !angular.isUndefined(ctrl.disableChoiceExpression)) {
333+
if (itemIndex >= 0 && (!angular.isUndefined(ctrl.disableChoiceExpression) || ctrl.multiple)) {
329334
item = ctrl.items[itemIndex];
330-
isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression)); // force the boolean value
335+
isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression)) || _isItemSelected(item); // force the boolean value
331336
item._uiSelectChoiceDisabled = isDisabled; // store this for later reference
332337
}
333338

@@ -375,7 +380,7 @@ uis.controller('uiSelectCtrl',
375380
}
376381
}
377382
// search ctrl.selected for dupes potentially caused by tagging and return early if found
378-
if ( ctrl.selected && angular.isArray(ctrl.selected) && ctrl.selected.filter( function (selection) { return angular.equals(selection, item); }).length > 0 ) {
383+
if (_isItemSelected(item)) {
379384
ctrl.close(skipFocusser);
380385
return;
381386
}

‎src/uiSelectDirective.js

+5
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ uis.directive('uiSelect',
8787
$select.sortable = sortable !== undefined ? sortable : uiSelectConfig.sortable;
8888
});
8989

90+
scope.$watch('removeSelected', function() {
91+
var removeSelected = scope.$eval(attrs.removeSelected);
92+
$select.removeSelected = removeSelected !== undefined ? removeSelected : uiSelectConfig.removeSelected;
93+
});
94+
9095
attrs.$observe('disabled', function() {
9196
// No need to use $eval() (thanks to ng-disabled) since we already get a boolean instead of a string
9297
$select.disabled = attrs.disabled !== undefined ? attrs.disabled : false;

‎src/uiSelectMultipleDirective.js

-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec
7676
//$select.selected = raw selected objects (ignoring any property binding)
7777

7878
$select.multiple = true;
79-
$select.removeSelected = true;
8079

8180
//Input that will handle focus
8281
$select.focusInput = $select.searchInput;

‎test/select.spec.js

+50
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,56 @@ describe('ui-select tests', function() {
14271427
expect($(el).scope().$select.selected).toEqual(['idontexist']);
14281428
});
14291429

1430+
it('should remove a choice when remove-selected is not given (default is true)', function () {
1431+
1432+
var el = compileTemplate(
1433+
'<ui-select multiple ng-model="selection.selected"> \
1434+
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
1435+
<ui-select-choices repeat="person in people | filter: $select.search"> \
1436+
<div class="person-name" ng-bind-html="person.name" | highlight: $select.search"></div> \
1437+
<div ng-bind-html="person.email | highlight: $select.search"></div> \
1438+
</ui-select-choices> \
1439+
</ui-select>'
1440+
);
1441+
1442+
clickItem(el, 'Samantha');
1443+
clickItem(el, 'Adrian');
1444+
1445+
openDropdown(el);
1446+
1447+
var choicesEls = $(el).find('.ui-select-choices-row');
1448+
expect(choicesEls.length).toEqual(6);
1449+
1450+
['Adam', 'Amalie', 'Estefanía', 'Wladimir', 'Nicole', 'Natasha'].forEach(function (name, index) {
1451+
expect($(choicesEls[index]).hasClass('disabled')).toBeFalsy();
1452+
expect($(choicesEls[index]).find('.person-name').text()).toEqual(name);
1453+
});
1454+
});
1455+
1456+
it('should disable a choice instead of removing it when remove-selected is false', function () {
1457+
1458+
var el = compileTemplate(
1459+
'<ui-select multiple remove-selected="false" ng-model="selection.selected"> \
1460+
<ui-select-match placeholder="Pick one...">{{$select.selected.name}}</ui-select-match> \
1461+
<ui-select-choices repeat="person in people | filter: $select.search"> \
1462+
<div ng-bind-html="person.name" | highlight: $select.search"></div> \
1463+
<div ng-bind-html="person.email | highlight: $select.search"></div> \
1464+
</ui-select-choices> \
1465+
</ui-select>'
1466+
);
1467+
1468+
clickItem(el, 'Samantha');
1469+
clickItem(el, 'Adrian');
1470+
1471+
openDropdown(el);
1472+
1473+
var choicesEls = $(el).find('.ui-select-choices-row');
1474+
expect(choicesEls.length).toEqual(8);
1475+
[false, false, false, true /* Adrian */, false, true /* Samantha */, false, false].forEach(function (bool, index) {
1476+
expect($(choicesEls[index]).hasClass('disabled')).toEqual(bool);
1477+
});
1478+
});
1479+
14301480
it('should append/transclude content (with correct scope) that users add at <match> tag', function () {
14311481

14321482
var el = compileTemplate(

0 commit comments

Comments
 (0)
Please sign in to comment.