Skip to content

Commit 79b5e00

Browse files
fix(uiSelectSingle): Tagging without multiple with new tags doesn't works
Tagging in single select is not working which has been testing in latest version of angular. Here, I've just copied working version of code from uiSelectMultiple directive and removed some code which causes the problem. All the test has been passed. Examples are working fine Closes angular-ui#1409, angular-ui#890
1 parent 3dfde71 commit 79b5e00

7 files changed

+328
-21
lines changed

dist/select.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*!
22
* ui-select
33
* http://github.com/angular-ui/ui-select
4-
* Version: 0.18.1 - 2016-07-10T00:18:11.107Z
4+
* Version: 0.18.1 - 2016-07-20T20:40:49.941Z
55
* License: MIT
66
*/
77

dist/select.js

Lines changed: 171 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*!
22
* ui-select
33
* http://github.com/angular-ui/ui-select
4-
* Version: 0.18.1 - 2016-07-10T00:18:10.535Z
4+
* Version: 0.18.1 - 2016-07-20T20:40:49.880Z
55
* License: MIT
66
*/
77

@@ -630,15 +630,15 @@ uis.controller('uiSelectCtrl',
630630
function _isItemDisabled(item) {
631631
return disabledItems.indexOf(item) > -1;
632632
}
633-
633+
634634
ctrl.isDisabled = function(itemScope) {
635635

636636
if (!ctrl.open) return;
637637

638638
var item = itemScope[ctrl.itemProperty];
639639
var itemIndex = ctrl.items.indexOf(item);
640640
var isDisabled = false;
641-
641+
642642
if (itemIndex >= 0 && (angular.isDefined(ctrl.disableChoiceExpression) || ctrl.multiple)) {
643643

644644
if (item.isTag) return false;
@@ -650,7 +650,7 @@ uis.controller('uiSelectCtrl',
650650
if (!isDisabled && angular.isDefined(ctrl.disableChoiceExpression)) {
651651
isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression));
652652
}
653-
653+
654654
_updateItemDisabled(item, isDisabled);
655655
}
656656

@@ -665,7 +665,12 @@ uis.controller('uiSelectCtrl',
665665
if ( ! ctrl.items && ! ctrl.search && ! ctrl.tagging.isActivated) return;
666666

667667
if (!item || !_isItemDisabled(item)) {
668-
if(ctrl.tagging.isActivated) {
668+
// if click is made on existing item, prevent from tagging, ctrl.search does not matter
669+
ctrl.clickTriggeredSelect = false;
670+
if($event && $event.type === 'click' && item)
671+
ctrl.clickTriggeredSelect = true;
672+
673+
if(ctrl.tagging.isActivated && ctrl.clickTriggeredSelect === false) {
669674
// if taggingLabel is disabled and item is undefined we pull from ctrl.search
670675
if ( ctrl.taggingLabel === false ) {
671676
if ( ctrl.activeIndex < 0 ) {
@@ -721,9 +726,6 @@ uis.controller('uiSelectCtrl',
721726
if (ctrl.closeOnSelect) {
722727
ctrl.close(skipFocusser);
723728
}
724-
if ($event && $event.type === 'click') {
725-
ctrl.clickTriggeredSelect = true;
726-
}
727729
}
728730
}
729731
};
@@ -762,7 +764,7 @@ uis.controller('uiSelectCtrl',
762764
}
763765
};
764766

765-
// Set default function for locked choices - avoids unnecessary
767+
// Set default function for locked choices - avoids unnecessary
766768
// logic if functionality is not being used
767769
ctrl.isLocked = function () {
768770
return false;
@@ -774,7 +776,7 @@ uis.controller('uiSelectCtrl',
774776

775777
function _initaliseLockedChoices(doInitalise) {
776778
if(!doInitalise) return;
777-
779+
778780
var lockedItems = [];
779781

780782
function _updateItemLocked(item, isLocked) {
@@ -808,7 +810,7 @@ uis.controller('uiSelectCtrl',
808810
return isLocked;
809811
};
810812
}
811-
813+
812814

813815
var sizeWatch = null;
814816
var updaterScheduled = false;
@@ -1386,6 +1388,8 @@ uis.directive('uiSelect',
13861388
});
13871389
};
13881390

1391+
var opened = false;
1392+
13891393
scope.calculateDropdownPos = function() {
13901394
if ($select.open) {
13911395
dropdown = angular.element(element).querySelectorAll('.ui-select-dropdown');
@@ -1394,8 +1398,11 @@ uis.directive('uiSelect',
13941398
return;
13951399
}
13961400

1397-
// Hide the dropdown so there is no flicker until $timeout is done executing.
1398-
dropdown[0].style.opacity = 0;
1401+
// Hide the dropdown so there is no flicker until $timeout is done executing.
1402+
if ($select.search === '' && !opened) {
1403+
dropdown[0].style.opacity = 0;
1404+
opened = true;
1405+
}
13991406

14001407
if (!uisOffset(dropdown).height && $select.$animate && $select.$animate.on && $select.$animate.enabled(dropdown)) {
14011408
var needsCalculated = true;
@@ -2065,6 +2072,156 @@ uis.directive('uiSelectSingle', ['$timeout','$compile', function($timeout, $comp
20652072

20662073
});
20672074

2075+
//Copied from multiselect
2076+
$select.searchInput.on('keyup', function (e) {
2077+
2078+
if (!KEY.isVerticalMovement(e.which)) {
2079+
scope.$evalAsync(function () {
2080+
$select.activeIndex = $select.taggingLabel === false ? -1 : 0;
2081+
});
2082+
}
2083+
// Push a "create new" item into array if there is a search string
2084+
if ($select.tagging.isActivated && $select.search.length > 0) {
2085+
2086+
// return early with these keys
2087+
if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || KEY.isVerticalMovement(e.which)) {
2088+
return;
2089+
}
2090+
// always reset the activeIndex to the first item when tagging
2091+
$select.activeIndex = $select.taggingLabel === false ? -1 : 0;
2092+
// taggingLabel === false bypasses all of this
2093+
if ($select.taggingLabel === false) return;
2094+
2095+
var items = angular.copy($select.items);
2096+
var stashArr = angular.copy($select.items);
2097+
var newItem;
2098+
var item;
2099+
var hasTag = false;
2100+
var dupeIndex = -1;
2101+
var tagItems;
2102+
var tagItem;
2103+
2104+
// case for object tagging via transform `$select.tagging.fct` function
2105+
if ($select.tagging.fct !== undefined) {
2106+
tagItems = $select.$filter('filter')(items, { 'isTag': true });
2107+
if (tagItems.length > 0) {
2108+
tagItem = tagItems[0];
2109+
}
2110+
// remove the first element, if it has the `isTag` prop we generate a new one with each keyup, shaving the previous
2111+
if (items.length > 0 && tagItem) {
2112+
hasTag = true;
2113+
items = items.slice(1, items.length);
2114+
stashArr = stashArr.slice(1, stashArr.length);
2115+
}
2116+
newItem = $select.tagging.fct($select.search);
2117+
// verify the new tag doesn't match the value of a possible selection choice or an already selected item.
2118+
if (
2119+
stashArr.some(function (origItem) {
2120+
return angular.equals(origItem, newItem);
2121+
})) {
2122+
scope.$evalAsync(function () {
2123+
$select.activeIndex = 0;
2124+
$select.items = items;
2125+
});
2126+
return;
2127+
}
2128+
if (newItem) newItem.isTag = true;
2129+
// handle newItem string and stripping dupes in tagging string context
2130+
} else {
2131+
// find any tagging items already in the $select.items array and store them
2132+
tagItems = $select.$filter('filter')(items, function (item) {
2133+
return item.match($select.taggingLabel);
2134+
});
2135+
if (tagItems.length > 0) {
2136+
tagItem = tagItems[0];
2137+
}
2138+
item = items[0];
2139+
// remove existing tag item if found (should only ever be one tag item)
2140+
if (item !== undefined && items.length > 0 && tagItem) {
2141+
hasTag = true;
2142+
items = items.slice(1, items.length);
2143+
stashArr = stashArr.slice(1, stashArr.length);
2144+
}
2145+
newItem = $select.search + ' ' + $select.taggingLabel;
2146+
if (_findApproxDupe($select.selected, $select.search) > -1) {
2147+
return;
2148+
}
2149+
// verify the the tag doesn't match the value of an existing item from
2150+
// the searched data set or the items already selected
2151+
if (_findCaseInsensitiveDupe(stashArr.concat($select.selected))) {
2152+
// if there is a tag from prev iteration, strip it / queue the change
2153+
// and return early
2154+
if (hasTag) {
2155+
items = stashArr;
2156+
scope.$evalAsync(function () {
2157+
$select.activeIndex = 0;
2158+
$select.items = items;
2159+
});
2160+
}
2161+
return;
2162+
}
2163+
if (_findCaseInsensitiveDupe(stashArr)) {
2164+
// if there is a tag from prev iteration, strip it
2165+
if (hasTag) {
2166+
$select.items = stashArr.slice(1, stashArr.length);
2167+
}
2168+
return;
2169+
}
2170+
}
2171+
if (hasTag) dupeIndex = _findApproxDupe($select.selected, newItem);
2172+
// dupe found, shave the first item
2173+
if (dupeIndex > -1) {
2174+
items = items.slice(dupeIndex + 1, items.length - 1);
2175+
} else {
2176+
items = [];
2177+
if (newItem) items.push(newItem);
2178+
items = items.concat(stashArr);
2179+
}
2180+
scope.$evalAsync(function () {
2181+
$select.activeIndex = 0;
2182+
$select.items = items;
2183+
2184+
if ($select.isGrouped) {
2185+
// update item references in groups, so that indexOf will work after angular.copy
2186+
var itemsWithoutTag = newItem ? items.slice(1) : items;
2187+
$select.setItemsFn(itemsWithoutTag);
2188+
if (newItem) {
2189+
// add tag item as a new group
2190+
$select.items.unshift(newItem);
2191+
$select.groups.unshift({ name: '', items: [newItem], tagging: true });
2192+
}
2193+
}
2194+
});
2195+
}
2196+
});
2197+
2198+
//Copied from uiSelectMultipleDirective
2199+
function _findApproxDupe(haystack, needle) {
2200+
var dupeIndex = -1;
2201+
if (angular.isArray(haystack)) {
2202+
var tempArr = angular.copy(haystack);
2203+
for (var i = 0; i < tempArr.length; i++) {
2204+
// handle the simple string version of tagging
2205+
if ($select.tagging.fct === undefined) {
2206+
// search the array for the match
2207+
if (tempArr[i] + ' ' + $select.taggingLabel === needle) {
2208+
dupeIndex = i;
2209+
}
2210+
// handle the object tagging implementation
2211+
} else {
2212+
var mockObj = tempArr[i];
2213+
if (angular.isObject(mockObj)) {
2214+
mockObj.isTag = true;
2215+
}
2216+
if (angular.equals(mockObj, needle)) {
2217+
dupeIndex = i;
2218+
}
2219+
}
2220+
}
2221+
}
2222+
return dupeIndex;
2223+
}
2224+
20682225

20692226
}
20702227
};
@@ -2298,7 +2455,7 @@ uis.service('uisRepeatParser', ['uiSelectMinErr','$parse', function(uiSelectMinE
22982455
};
22992456

23002457
self.getGroupNgRepeatExpression = function() {
2301-
return '$group in $select.groups';
2458+
return '$group in $select.groups track by $group.name';
23022459
};
23032460

23042461
}]);

dist/select.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)