From 846b34cf4b0f155f6198c3cb708d9a157d3e2170 Mon Sep 17 00:00:00 2001 From: Rick Yang Date: Tue, 21 Feb 2017 11:53:29 +0800 Subject: [PATCH] Change to set null instead of undefined when ctrl is clear [why] Null is more readable for empty value. [how] * When ctrl is cleared, set null to its selection. * In ngModel.$parsers, add a handler to ) return null for null value. ) return undefined for undefined value. * Also modify test case for checking clear value. --- src/uiSelectController.js | 8 ++++---- src/uiSelectMultipleDirective.js | 21 ++++++++++++++------- src/uiSelectSingleDirective.js | 14 +++++++++++--- test/select.spec.js | 8 ++++---- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/uiSelectController.js b/src/uiSelectController.js index e304279d4..b3c3c593f 100644 --- a/src/uiSelectController.js +++ b/src/uiSelectController.js @@ -376,7 +376,7 @@ 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 (item === undefined || item === null || !_isItemDisabled(item)) { if ( ! ctrl.items && ! ctrl.search && ! ctrl.tagging.isActivated) return; @@ -390,7 +390,7 @@ uis.controller('uiSelectCtrl', // if taggingLabel is disabled and item is undefined we pull from ctrl.search if ( ctrl.taggingLabel === false ) { if ( ctrl.activeIndex < 0 ) { - if (item === undefined) { + if (item === undefined || item === null) { item = ctrl.tagging.fct !== undefined ? ctrl.tagging.fct(ctrl.search) : ctrl.search; } if (!item || angular.equals( ctrl.items[0], item ) ) { @@ -406,7 +406,7 @@ uis.controller('uiSelectCtrl', 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; + if ( item === undefined || item === null) return; // create new item on the fly if we don't already have one; // use tagging function if we have one @@ -451,7 +451,7 @@ uis.controller('uiSelectCtrl', }; ctrl.clear = function($event) { - ctrl.select(undefined); + ctrl.select(null); $event.stopPropagation(); $timeout(function() { ctrl.focusser[0].focus(); diff --git a/src/uiSelectMultipleDirective.js b/src/uiSelectMultipleDirective.js index 1d0243724..d74018603 100644 --- a/src/uiSelectMultipleDirective.js +++ b/src/uiSelectMultipleDirective.js @@ -96,9 +96,16 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec result, resultMultiple = []; for (var j = $select.selected.length - 1; j >= 0; j--) { - locals = {}; - locals[$select.parserResult.itemName] = $select.selected[j]; - result = $select.parserResult.modelMapper(scope, locals); + // Keep original value for undefined and null + var selected = $select.selected[j]; + if ( selected === undefined || selected === null) { + result = selected; + } else { + locals = {}; + locals[$select.parserResult.itemName] = selected; + result = $select.parserResult.modelMapper(scope, locals); + } + resultMultiple.unshift(result); } return resultMultiple; @@ -178,7 +185,7 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec return; } $select.selected.push(item); - var locals = {}; + var locals = {}; locals[$select.parserResult.itemName] = item; $timeout(function(){ @@ -261,11 +268,11 @@ uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelec } else { return curr; } - + } else { // If nothing yet selected, select last item - return last; - } + return last; + } break; case KEY.DELETE: // Remove selected item and select next item diff --git a/src/uiSelectSingleDirective.js b/src/uiSelectSingleDirective.js index 4d001dad9..7a4eb8558 100644 --- a/src/uiSelectSingleDirective.js +++ b/src/uiSelectSingleDirective.js @@ -11,8 +11,16 @@ uis.directive('uiSelectSingle', ['$timeout','$compile', function($timeout, $comp ngModel.$parsers.unshift(function (inputValue) { var locals = {}, result; - locals[$select.parserResult.itemName] = inputValue; - result = $select.parserResult.modelMapper(scope, locals); + + // Keep original value for undefined and null + if (inputValue === undefined || inputValue === null) { + result = inputValue; + } + else { + locals[$select.parserResult.itemName] = inputValue; + result = $select.parserResult.modelMapper(scope, locals); + } + return result; }); @@ -51,7 +59,7 @@ uis.directive('uiSelectSingle', ['$timeout','$compile', function($timeout, $comp scope.$on('uis:select', function (event, item) { $select.selected = item; - var locals = {}; + var locals = {}; locals[$select.parserResult.itemName] = item; $timeout(function(){ diff --git a/test/select.spec.js b/test/select.spec.js index 8c1cf44c7..39705fb5c 100644 --- a/test/select.spec.js +++ b/test/select.spec.js @@ -553,7 +553,7 @@ describe('ui-select tests', function() { // Trigger clear. el.find('.select2-search-choice-close').click(); - expect(scope.selection.selected).toEqual(undefined); + expect(scope.selection.selected).toEqual(null); // If there is no selection it the X icon should be gone. expect(el.find('.select2-search-choice-close').length).toEqual(0); @@ -3231,12 +3231,12 @@ describe('ui-select tests', function() { expect(el.scope().$select.spinnerClass).toBe('randomclass'); }); }); - + describe('With refresh on active', function(){ it('should refresh when is activated', function(){ scope.fetchFromServer = function(){}; var el = createUiSelect({refresh:"fetchFromServer($select.search)",refreshDelay:0}); - spyOn(scope, 'fetchFromServer'); + spyOn(scope, 'fetchFromServer'); expect(el.scope().$select.open).toEqual(false); el.scope().$select.activate(); $timeout.flush(); @@ -3248,7 +3248,7 @@ describe('ui-select tests', function() { it('should refresh when open is set to true', function(){ scope.fetchFromServer = function(){}; var el = createUiSelect({refresh:"fetchFromServer($select.search)",refreshDelay:0}); - spyOn(scope, 'fetchFromServer'); + spyOn(scope, 'fetchFromServer'); expect(el.scope().$select.open).toEqual(false); openDropdown(el); $timeout.flush();