Skip to content
This repository has been archived by the owner on May 29, 2019. It is now read-only.

Commit

Permalink
feat(typeahead): Adds 'select on exact'.
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonTypesCodes committed Jul 22, 2015
1 parent 4af83ad commit 9df2912
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 5 deletions.
14 changes: 9 additions & 5 deletions src/typeahead/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ The typeahead directives provide several attributes:
* `typeahead-editable` <i class="glyphicon glyphicon-eye-open"></i>
_(Defaults: true)_ :
Should it restrict model values to the ones selected from the popup only ?

* `typeahead-focus-first`
_(Defaults: true)_ :
Should the first match automatically be focused as you type?

* `typeahead-input-formatter` <i class="glyphicon glyphicon-eye-open"></i>
_(Defaults: undefined)_ :
Expand All @@ -39,11 +43,15 @@ The typeahead directives provide several attributes:
* `typeahead-min-length` <i class="glyphicon glyphicon-eye-open"></i>
_(Defaults: 1)_ :
Minimal no of characters that needs to be entered before typeahead kicks-in

* `typeahead-on-select($item, $model, $label)`
_(Defaults: null)_ :
A callback executed when a match is selected

* `typeahead-select-on-exact`
_(Defaults: false)_ :
Should it automatically select an item when there is one option that exactly matches the user input?

* `typeahead-template-url` <i class="glyphicon glyphicon-eye-open"></i>
:
Set custom item template
Expand All @@ -52,10 +60,6 @@ The typeahead directives provide several attributes:
_(Defaults: 0)_ :
Minimal wait time after last character typed before typeahead kicks-in

* `typeahead-focus-first`
_(Defaults: true)_ :
Should the first match automatically be focused as you type?

* `select-on`blur`
_(Defaults: false)_ :
On blur, select the currently highlighted match
57 changes: 57 additions & 0 deletions src/typeahead/test/typeahead.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,63 @@ describe('typeahead tests', function () {
expect(inputEl.val()).toEqual('AL');
});
});

describe('select on exact match', function(){

it('should select on an exact match when set', function () {

$scope.onSelect = jasmine.createSpy('onSelect');
var element = prepareInputEl('<div><input ng-model="result" typeahead-editable="false" typeahead-on-select="onSelect()" typeahead="item for item in source | filter:$viewValue" typeahead-select-on-exact="true"></div>');
var inputEl = findInput(element);

changeInputValueTo(element, 'bar');

expect($scope.result).toEqual('bar');
expect(inputEl.val()).toEqual('bar');
expect(element).toBeClosed();
expect($scope.onSelect).toHaveBeenCalled();
});

it('should not select on an exact match by default', function () {

$scope.onSelect = jasmine.createSpy('onSelect');
var element = prepareInputEl('<div><input ng-model="result" typeahead-editable="false" typeahead-on-select="onSelect()" typeahead="item for item in source | filter:$viewValue"></div>');
var inputEl = findInput(element);

changeInputValueTo(element, 'bar');

expect($scope.result).toBeUndefined();
expect(inputEl.val()).toEqual('bar');
expect($scope.onSelect.calls.any()).toBe(false);
});

it('should not be case sensitive when select on an exact match', function () {

$scope.onSelect = jasmine.createSpy('onSelect');
var element = prepareInputEl('<div><input ng-model="result" typeahead-editable="false" typeahead-on-select="onSelect()" typeahead="item for item in source | filter:$viewValue" typeahead-select-on-exact="true"></div>');
var inputEl = findInput(element);

changeInputValueTo(element, 'BaR');

expect($scope.result).toEqual('bar');
expect(inputEl.val()).toEqual('bar');
expect(element).toBeClosed();
expect($scope.onSelect).toHaveBeenCalled();
});

it('should not auto select when not a match with one potential result left', function () {

$scope.onSelect = jasmine.createSpy('onSelect');
var element = prepareInputEl('<div><input ng-model="result" typeahead-editable="false" typeahead-on-select="onSelect()" typeahead="item for item in source | filter:$viewValue" typeahead-select-on-exact="true"></div>');
var inputEl = findInput(element);

changeInputValueTo(element, 'fo');

expect($scope.result).toBeUndefined();
expect(inputEl.val()).toEqual('fo');
expect($scope.onSelect.calls.any()).toBe(false);
});
});

describe('pop-up interaction', function () {
var element;
Expand Down
17 changes: 17 additions & 0 deletions src/typeahead/typeahead.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;

var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;

//If input matches an item of the list exactly, select it automatically
var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;

//INTERNAL VARIABLES

Expand Down Expand Up @@ -128,6 +131,15 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
element.attr('aria-activedescendant', getMatchId(index));
}
});

var inputIsExactMatch = function(inputValue, index) {

if (scope.matches.length > index && inputValue){
return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase();
}

return false;
};

var getMatchesAsync = function(inputValue) {

Expand Down Expand Up @@ -161,6 +173,11 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
recalculatePosition();

element.attr('aria-expanded', true);

//Select the single remaining option if user input matches
if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)){
scope.select(0);
}
} else {
resetMatches();
}
Expand Down

0 comments on commit 9df2912

Please sign in to comment.