From 1187518b76a086df3a60246ceec3dd4446e6defd Mon Sep 17 00:00:00 2001 From: Hidenari Nozaki Date: Fri, 20 Jun 2014 23:21:43 +1200 Subject: [PATCH] Handle selectedObject as object or callback proposed by @nekcih in #6 --- README.md | 5 ++++- angucomplete-alt.js | 15 ++++++++++++--- test/angucomplete-alt.spec.js | 36 +++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 86ed27b1..2928f380 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,9 @@ To see a demo go here: http://ghiden.github.io/angucomplete-alt * Clear on selection: when you select an item, input field is cleared. * Blur event handling, thanks to @leejsinclair * Override suggestions +* You can either bind an object or callback function + * bind an object: it works as regular two-way-data-binding + * callback function: when a selection is made by user, this callback is called with the selected object. Thanks to @nekcih for proposing this feature. ### Getting Started Download the code, and include the angucomplete-alt.js file in your page. Then add the angucomplete-alt module to your Angular App file, e.g. @@ -65,7 +68,7 @@ var app = angular.module('app', ["angucomplete-alt"]); | id | A unique ID for the field | Yes | members | | placeholder | Placeholder text for the search field | No | Search members | | pause | The time to wait (in milliseconds) before searching when the user enters new characters | No | 400 | -| selected-object | Where to store the selected object in your model/controller (like ng-model) | Yes | myObject | +| selected-object | Either an object in your scope or callback function. If you set an object, it will be two-way-bound data as usual. If you set a callback, it gets called when selection is made. | Yes | selectedObject or objectSelectedCallback | | remote-url | The remote URL to hit to query for results in JSON. angucomplete will automatically append the search string on the end of this, so it must be a GET request | No | http://myserver.com/api/users/find?searchstr= | | remote-url-data-field | The name of the field in the JSON object returned back that holds the Array of objects to be used for the autocomplete list. | No | results | | title-field | The name of the field in the JSON objects returned back that should be used for displaying the title in the autocomplete list. Note, if you want to combine fields together, you can comma separate them here (e.g. for a first and last name combined) | Yes | firstName,lastName | diff --git a/angucomplete-alt.js b/angucomplete-alt.js index 0865de12..9655dabc 100644 --- a/angucomplete-alt.js +++ b/angucomplete-alt.js @@ -70,6 +70,15 @@ angular.module('angucomplete-alt', [] ).directive('angucompleteAlt', ['$parse', scope.searching = false; scope.searchStr = null; + var callOrAssign = function(value) { + if (typeof scope.selectedObject === 'function') { + scope.selectedObject(value); + } + else { + scope.selectedObject = value; + } + }; + var returnFunctionOrIdentity = function(fn) { return fn && typeof fn === 'function' ? fn : function(data) { return data; }; }; @@ -77,7 +86,7 @@ angular.module('angucomplete-alt', [] ).directive('angucompleteAlt', ['$parse', var responseFormatter = returnFunctionOrIdentity(scope.remoteUrlResponseFormatter); var setInputString = function(str) { - scope.selectedObject = {originalObject: str}; + callOrAssign({originalObject: str}); if (scope.clearSelected) { scope.searchStr = null; @@ -283,7 +292,7 @@ angular.module('angucomplete-alt', [] ).directive('angucompleteAlt', ['$parse', else { scope.searchStr = lastSearchTerm = result.title; } - scope.selectedObject = result; + callOrAssign(result); scope.showDropdown = false; scope.results = []; }; @@ -330,7 +339,7 @@ angular.module('angucomplete-alt', [] ).directive('angucompleteAlt', ['$parse', scope.showDropdown = false; scope.$apply(); } else if (event.which === KEY_BS || event.which === KEY_DEL) { - scope.selectedObject = null; + callOrAssign(null); scope.$apply(); } }); diff --git a/test/angucomplete-alt.spec.js b/test/angucomplete-alt.spec.js index 32b0e0c8..616494b3 100644 --- a/test/angucomplete-alt.spec.js +++ b/test/angucomplete-alt.spec.js @@ -499,4 +499,40 @@ describe('angucomplete-alt', function() { expect(element.isolateScope().searchStr).toBe(null); }); }); + + describe('selectedObject callback', function() { + it('should call selectedObject callback if given', function() { + var element = angular.element('
'); + var selected = false; + $scope.countrySelected = function(value) { + selected = true; + }; + $scope.countries = [ + {name: 'Afghanistan', code: 'AF'}, + {name: 'Aland Islands', code: 'AX'}, + {name: 'Albania', code: 'AL'} + ]; + $compile(element)($scope); + $scope.$digest(); + + expect(selected).toBe(false); + var inputField = element.find('#ex1_value'); + var e = $.Event('keyup'); + e.which = 97; // letter: a + + inputField.val('a'); + inputField.trigger('input'); + inputField.trigger(e); + $timeout.flush(); + expect(element.find('#ex1_dropdown').length).toBe(1); + + e.which = KEY_DW; + inputField.trigger(e); + expect(element.isolateScope().currentIndex).toBe(0); + + e.which = KEY_EN; + inputField.trigger(e); + expect(selected).toBe(true); + }); + }); });