diff --git a/src/uiSelectController.js b/src/uiSelectController.js
index b7dc2801c..e5bfd9ec1 100644
--- a/src/uiSelectController.js
+++ b/src/uiSelectController.js
@@ -369,73 +369,88 @@ uis.controller('uiSelectCtrl',
// When the user selects an item with ENTER or clicks the dropdown
- ctrl.select = function(item, skipFocusser, $event) {
- if (item === undefined || !_isItemDisabled(item)) {
-
- if ( ! ctrl.items && ! ctrl.search && ! ctrl.tagging.isActivated) return;
-
- if (!item || !_isItemDisabled(item)) {
- if(ctrl.tagging.isActivated) {
- // if taggingLabel is disabled and item is undefined we pull from ctrl.search
- if ( ctrl.taggingLabel === false ) {
- if ( ctrl.activeIndex < 0 ) {
- if (item === undefined) {
- item = ctrl.tagging.fct !== undefined ? ctrl.tagging.fct(ctrl.search) : ctrl.search;
- }
- if (!item || angular.equals( ctrl.items[0], item ) ) {
- return;
- }
- } else {
- // keyboard nav happened first, user selected from dropdown
- item = ctrl.items[ctrl.activeIndex];
- }
- } else {
- // tagging always operates at index zero, taggingLabel === false pushes
- // the ctrl.search value without having it injected
- if ( ctrl.activeIndex === 0 ) {
- // ctrl.tagging pushes items to ctrl.items, so we only have empty val
- // for `item` if it is a detected duplicate
- if ( item === undefined ) return;
-
- // create new item on the fly if we don't already have one;
- // use tagging function if we have one
- if ( ctrl.tagging.fct !== undefined && typeof item === 'string' ) {
- item = ctrl.tagging.fct(item);
- if (!item) return;
- // if item type is 'string', apply the tagging label
- } else if ( typeof item === 'string' ) {
- // trim the trailing space
- item = item.replace(ctrl.taggingLabel,'').trim();
- }
- }
- }
- // search ctrl.selected for dupes potentially caused by tagging and return early if found
- if (_isItemSelected(item)) {
- ctrl.close(skipFocusser);
- return;
- }
- }
-
- $scope.$broadcast('uis:select', item);
+ ctrl.select = function (item, skipFocusser, $event) {
- var locals = {};
- locals[ctrl.parserResult.itemName] = item;
+ if (angular.isDefined(item) && _isItemDisabled(item)) return;
- $timeout(function(){
- ctrl.onSelectCallback($scope, {
- $item: item,
- $model: ctrl.parserResult.modelMapper($scope, locals)
- });
- });
+ if (!ctrl.items && !ctrl.search && !ctrl.tagging.isActivated) return;
- if (ctrl.closeOnSelect) {
- ctrl.close(skipFocusser);
+ var dummyTaggingFunc = function(i) { return i; };
+ var taggingFunc = angular.isDefined(ctrl.tagging.fct) ? ctrl.tagging.fct
+ : dummyTaggingFunc;
+
+ var minActiveIndex = ctrl.taggingLabel === false ? -1 : 0;
+
+ // The ctrl.activeIndex might not be set (eg. if the user has clicked on an entry)
+ // check to see if the item exists, if so use its index as the active index
+ var itemIndex = minActiveIndex;
+ if(ctrl.activeIndex === minActiveIndex) {
+ var idx = ctrl.items.indexOf(item);
+ if(idx > -1) {
+ itemIndex = idx;
+ }
+ }
+
+ if(ctrl.tagging.isActivated && itemIndex === minActiveIndex) {
+
+ if(ctrl.taggingLabel !== false) {
+ // If item is undefined it'll remain undefined
+ // and be ignore later
+ item = _getCleanedTag(item);
+ } else {
+ if(angular.isUndefined(item)) {
+ item = taggingFunc(ctrl.search);
+ }
}
- if ($event && $event.type === 'click') {
- ctrl.clickTriggeredSelect = true;
+
+ // tagging function aborted selection
+ // or tagged item was a duplicate
+ if(!item) return;
+ }
+
+ // search ctrl.selected for dupes potentially caused by tagging and return early if found
+ if (_isItemSelected(item)) {
+ ctrl.close(skipFocusser);
+ return;
+ }
+
+ function _getCleanedTag(tagItem) {
+
+ if(angular.isString(tagItem)) {
+ if(taggingFunc === dummyTaggingFunc) {
+ // if there isn't a tagging function ensure tagging
+ // label is removed from value
+ tagItem = tagItem.replace(ctrl.taggingLabel, '').trim();
+ } else {
+ tagItem = ctrl.tagging.fct(tagItem);
}
}
+
+ return tagItem;
+ }
+
+ // if we don't have an item by now something has gone wrong
+ if (!item) return;
+
+ $scope.$broadcast('uis:select', item);
+
+ var locals = {};
+ locals[ctrl.parserResult.itemName] = item;
+
+ $timeout(function(){
+ ctrl.onSelectCallback($scope, {
+ $item: item,
+ $model: ctrl.parserResult.modelMapper($scope, locals)
+ });
+ });
+
+ if (ctrl.closeOnSelect) {
+ ctrl.close(skipFocusser);
}
+ if ($event && $event.type === 'click') {
+ ctrl.clickTriggeredSelect = true;
+ }
+
};
// Closes the dropdown
@@ -453,14 +468,6 @@ uis.controller('uiSelectCtrl',
if (!ctrl.focus) ctrl.focusInput[0].focus();
};
- ctrl.clear = function($event) {
- ctrl.select(undefined);
- $event.stopPropagation();
- $timeout(function() {
- ctrl.focusser[0].focus();
- }, 0, false);
- };
-
// Toggle dropdown
ctrl.toggle = function(e) {
if (ctrl.open) {
diff --git a/src/uiSelectSingleDirective.js b/src/uiSelectSingleDirective.js
index 73abedd23..e8c4fce0c 100644
--- a/src/uiSelectSingleDirective.js
+++ b/src/uiSelectSingleDirective.js
@@ -64,6 +64,14 @@ uis.directive('uiSelectSingle', ['$timeout','$compile', function($timeout, $comp
focusser.prop('disabled', true); //Will reactivate it on .close()
});
+ $select.clear = function($event) {
+ $select.selected = undefined;
+ $event.stopPropagation();
+ $timeout(function() {
+ $select.focusser[0].focus();
+ }, 0, false);
+ };
+
//Idea from: https://github.com/ivaynberg/select2/blob/79b5bf6db918d7560bdd959109b7bcfb47edaf43/select2.js#L1954
var focusser = angular.element("");
$compile(focusser)(scope);
diff --git a/test/select.spec.js b/test/select.spec.js
index 5b735689f..2865e0410 100644
--- a/test/select.spec.js
+++ b/test/select.spec.js
@@ -97,6 +97,10 @@ describe('ui-select tests', function() {
});
};
+ scope.simple = {
+ colors: ['Red', 'Green', 'Blue', 'Yellow', 'Magenta', 'Maroon', 'Umbra', 'Turquoise'],
+ selected: ['Red']
+ };
scope.people = [
{ name: 'Adam', email: 'adam@email.com', group: 'Foo', age: 12 },
@@ -620,7 +624,7 @@ describe('ui-select tests', function() {
expect($(el).scope().$select.selected).not.toBeDefined();
});
-
+
it('should allow tagging if the attribute says so', function() {
var el = createUiSelect({tagging: true});
clickMatch(el);
@@ -1402,6 +1406,43 @@ describe('ui-select tests', function() {
expect($(el).scope().$select.selected).toEqual('idontexist');
});
+ it('should allow tagging with simple string and no label if attribute says so', function () {
+
+ var el = compileTemplate(
+ ' \
+ {{$select.selected}} \
+ \
+ \
+ \
+ '
+ );
+
+ clickMatch(el);
+
+ $(el).scope().$select.select("I don't exist");
+
+ expect($(el).scope().$select.selected).toEqual(["Red", "I don't exist"]);
+ expect(scope.simple.selected).toEqual(['Red', "I don't exist"])
+ });
+
+ it('should not prevent selecting the first item when tagging with simple string and no label', function () {
+
+ var el = compileTemplate(
+ ' \
+ {{$item}} \
+ \
+ \
+ \
+ '
+ );
+
+ // ensure test source array has not changed
+ expect(scope.simple.colors[1]).toBe('Green');
+ clickItem(el, 'Green');
+
+ expect(scope.simple.selected).toEqual(['Red', 'Green']);
+ });
+
it('should allow creating tag on ENTER in multiple select mode with tagging enabled, no labels', function() {
scope.taggingFunc = function (name) {