diff --git a/docs/assets/demo.js b/docs/assets/demo.js index 7aaf3364e..f9999d4a7 100644 --- a/docs/assets/demo.js +++ b/docs/assets/demo.js @@ -175,6 +175,7 @@ app.controller('DemoCtrl', function ($scope, $http, $timeout, $interval) { vm.multipleDemo.selectedPeople2 = vm.multipleDemo.selectedPeople; vm.multipleDemo.selectedPeopleWithGroupBy = [vm.people[8], vm.people[6]]; vm.multipleDemo.selectedPeopleSimple = ['samantha@email.com','wladimir@email.com']; + vm.multipleDemo.removeSelectIsFalse = [vm.people[2], vm.people[0]]; vm.appendToBodyDemo = { remainingToggleTime: 0, diff --git a/docs/examples/demo-multiple-selection.html b/docs/examples/demo-multiple-selection.html index 54d23e5be..799c8430d 100644 --- a/docs/examples/demo-multiple-selection.html +++ b/docs/examples/demo-multiple-selection.html @@ -72,4 +72,18 @@

Array of objects (with groupBy)

Selected: {{multipleDemo.selectedPeopleWithGroupBy}}

+
+

Disabling instead of removing selected items

+ + {{$item.name}} <{{$item.email}}> + +
+ + email: {{person.email}} + age: + +
+
+

Selected: {{multipleDemo.removeSelectIsFalse}}

+
diff --git a/src/common.js b/src/common.js index 93e206324..45d88acfc 100644 --- a/src/common.js +++ b/src/common.js @@ -101,6 +101,7 @@ var uis = angular.module('ui.select', []) closeOnSelect: true, skipFocusser: false, dropdownPosition: 'auto', + removeSelected: true, generateId: function() { return latestId++; }, diff --git a/src/uiSelectController.js b/src/uiSelectController.js index 9e0968c3b..e35c1dac7 100644 --- a/src/uiSelectController.js +++ b/src/uiSelectController.js @@ -18,7 +18,7 @@ uis.controller('uiSelectCtrl', ctrl.refreshDelay = uiSelectConfig.refreshDelay; ctrl.paste = uiSelectConfig.paste; - ctrl.removeSelected = false; //If selected item(s) should be removed from dropdown list + ctrl.removeSelected = uiSelectConfig.removeSelected; //If selected item(s) should be removed from dropdown list ctrl.closeOnSelect = true; //Initialized inside uiSelect directive link function ctrl.skipFocusser = false; //Set to true to avoid returning focus to ctrl when item is selected ctrl.search = EMPTY_SEARCH; @@ -240,9 +240,9 @@ uis.controller('uiSelectCtrl', }else{ if ( data !== undefined ) { var filteredItems = data.filter(function(i) { - return selectedItems.every(function(selectedItem) { + return angular.isArray(selectedItems) ? selectedItems.every(function(selectedItem) { return !angular.equals(i, selectedItem); - }); + }) : !angular.equals(i, selectedItems); }); ctrl.setItemsFn(filteredItems); } @@ -317,6 +317,11 @@ uis.controller('uiSelectCtrl', return isActive; }; + var _isItemSelected = function (item) { + return (ctrl.selected && angular.isArray(ctrl.selected) && + ctrl.selected.filter(function (selection) { return angular.equals(selection, item); }).length > 0); + }; + ctrl.isDisabled = function(itemScope) { if (!ctrl.open) return; @@ -325,9 +330,9 @@ uis.controller('uiSelectCtrl', var isDisabled = false; var item; - if (itemIndex >= 0 && !angular.isUndefined(ctrl.disableChoiceExpression)) { + if (itemIndex >= 0 && (!angular.isUndefined(ctrl.disableChoiceExpression) || ctrl.multiple)) { item = ctrl.items[itemIndex]; - isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression)); // force the boolean value + isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression)) || _isItemSelected(item); // force the boolean value item._uiSelectChoiceDisabled = isDisabled; // store this for later reference } @@ -375,7 +380,7 @@ uis.controller('uiSelectCtrl', } } // search ctrl.selected for dupes potentially caused by tagging and return early if found - if ( ctrl.selected && angular.isArray(ctrl.selected) && ctrl.selected.filter( function (selection) { return angular.equals(selection, item); }).length > 0 ) { + if (_isItemSelected(item)) { ctrl.close(skipFocusser); return; } diff --git a/src/uiSelectDirective.js b/src/uiSelectDirective.js index 3032d8168..64cc517c1 100644 --- a/src/uiSelectDirective.js +++ b/src/uiSelectDirective.js @@ -87,6 +87,11 @@ uis.directive('uiSelect', $select.sortable = sortable !== undefined ? sortable : uiSelectConfig.sortable; }); + scope.$watch('removeSelected', function() { + var removeSelected = scope.$eval(attrs.removeSelected); + $select.removeSelected = removeSelected !== undefined ? removeSelected : uiSelectConfig.removeSelected; + }); + attrs.$observe('disabled', function() { // No need to use $eval() (thanks to ng-disabled) since we already get a boolean instead of a string $select.disabled = attrs.disabled !== undefined ? attrs.disabled : false; diff --git a/src/uiSelectMultipleDirective.js b/src/uiSelectMultipleDirective.js index a9b5b3e9e..e8ce8a7e5 100644 --- a/src/uiSelectMultipleDirective.js +++ b/src/uiSelectMultipleDirective.js @@ -76,7 +76,6 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec //$select.selected = raw selected objects (ignoring any property binding) $select.multiple = true; - $select.removeSelected = true; //Input that will handle focus $select.focusInput = $select.searchInput; diff --git a/test/select.spec.js b/test/select.spec.js index 3594b7468..106244532 100644 --- a/test/select.spec.js +++ b/test/select.spec.js @@ -1427,6 +1427,56 @@ describe('ui-select tests', function() { expect($(el).scope().$select.selected).toEqual(['idontexist']); }); + it('should remove a choice when remove-selected is not given (default is true)', function () { + + var el = compileTemplate( + ' \ + {{$select.selected.name}} \ + \ +
\ +
\ +
\ +
' + ); + + clickItem(el, 'Samantha'); + clickItem(el, 'Adrian'); + + openDropdown(el); + + var choicesEls = $(el).find('.ui-select-choices-row'); + expect(choicesEls.length).toEqual(6); + + ['Adam', 'Amalie', 'Estefanía', 'Wladimir', 'Nicole', 'Natasha'].forEach(function (name, index) { + expect($(choicesEls[index]).hasClass('disabled')).toBeFalsy(); + expect($(choicesEls[index]).find('.person-name').text()).toEqual(name); + }); + }); + + it('should disable a choice instead of removing it when remove-selected is false', function () { + + var el = compileTemplate( + ' \ + {{$select.selected.name}} \ + \ +
\ +
\ +
\ +
' + ); + + clickItem(el, 'Samantha'); + clickItem(el, 'Adrian'); + + openDropdown(el); + + var choicesEls = $(el).find('.ui-select-choices-row'); + expect(choicesEls.length).toEqual(8); + [false, false, false, true /* Adrian */, false, true /* Samantha */, false, false].forEach(function (bool, index) { + expect($(choicesEls[index]).hasClass('disabled')).toEqual(bool); + }); + }); + it('should append/transclude content (with correct scope) that users add at tag', function () { var el = compileTemplate(