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

Commit

Permalink
feat(typeahead): add 'is-open' support
Browse files Browse the repository at this point in the history
- Adds support for checking the toggled state of the dropdown

Closes #4760
Closes #4779
  • Loading branch information
chenyuzhcy authored and wesleycho committed Oct 29, 2015
1 parent a8624e0 commit 167cfad
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 4 deletions.
4 changes: 4 additions & 0 deletions src/typeahead/docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,7 @@ The typeahead directives provide several attributes:
* `typeahead-focus-on-select`
_(Defaults: true) :
On selection, focus the input element the typeahead directive is associated with

* `typeahead-is-open` <i class="glyphicon glyphicon-eye-open"></i>
_(Defaults: angular.noop)_ :
Binding to a variable that indicates if dropdown is open
72 changes: 72 additions & 0 deletions src/typeahead/test/typeahead.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,78 @@ describe('typeahead tests', function() {
});
});

describe('is-open indicator', function () {
var element;

beforeEach(function () {
element = prepareInputEl('<div><input ng-model="result" uib-typeahead="item for item in source | filter:$viewValue" typeahead-is-open="isOpen"></div>');
});

it('should bind is-open indicator as true when matches are returned', function () {
expect($scope.isOpen).toBeFalsy();
changeInputValueTo(element, 'b');
expect($scope.isOpen).toBeTruthy();
});

it('should bind is-open indicator as false when no matches returned', function () {
expect($scope.isOpen).toBeFalsy();
changeInputValueTo(element, 'b');
expect($scope.isOpen).toBeTruthy();
changeInputValueTo(element, 'not match');
expect($scope.isOpen).toBeFalsy();
});

it('should bind is-open indicator as false when a match is clicked', function () {
expect($scope.isOpen).toBeFalsy();
changeInputValueTo(element, 'b');
expect($scope.isOpen).toBeTruthy();
var match = findMatches(element).find('a').eq(0);

match.click();
$scope.$digest();
expect($scope.isOpen).toBeFalsy();
});
it('should bind is-open indicator as false when click outside', function () {
expect($scope.isOpen).toBeFalsy();
changeInputValueTo(element, 'b');
expect($scope.isOpen).toBeTruthy();
$document.find('body').click();
$scope.$digest();
expect($scope.isOpen).toBeFalsy();
});

it('should bind is-open indicator as false on enter', function () {
expect($scope.isOpen).toBeFalsy();
changeInputValueTo(element, 'b');
expect($scope.isOpen).toBeTruthy();
triggerKeyDown(element, 13);
expect($scope.isOpen).toBeFalsy();
});

it('should bind is-open indicator as false on tab', function () {
expect($scope.isOpen).toBeFalsy();
changeInputValueTo(element, 'b');
expect($scope.isOpen).toBeTruthy();
triggerKeyDown(element, 9);
expect($scope.isOpen).toBeFalsy();
});

it('should bind is-open indicator as false on escape key', function () {
expect($scope.isOpen).toBeFalsy();
changeInputValueTo(element, 'b');
expect($scope.isOpen).toBeTruthy();
triggerKeyDown(element, 27);
expect($scope.isOpen).toBeFalsy();
});

it('should bind is-open indicator as false input value smaller than a defined threshold', function () {
var element = prepareInputEl('<div><input ng-model="result" uib-typeahead="item for item in source | filter:$viewValue" typeahead-is-open="isToggled" typeahead-min-length="2"></div>');
expect($scope.isToggled).toBeFalsy();
changeInputValueTo(element, 'b');
expect($scope.isToggled).toBeFalsy();
});
});

describe('pop-up interaction', function() {
var element;

Expand Down
19 changes: 15 additions & 4 deletions src/typeahead/typeahead.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
//If input matches an item of the list exactly, select it automatically
var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;

//binding to a variable that indicates if dropdown is open
var isOpenSetter = $parse(attrs.typeaheadIsOpen).assign || angular.noop;

//INTERNAL VARIABLES

//model setter executed upon match selection
Expand Down Expand Up @@ -117,7 +120,8 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
select: 'select(activeIdx)',
'move-in-progress': 'moveInProgress',
query: 'query',
position: 'position'
position: 'position',
'assign-is-open': 'assignIsOpen(isOpen)'
});
//custom item template
if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
Expand Down Expand Up @@ -268,6 +272,10 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])

resetMatches();

scope.assignIsOpen = function (isOpen) {
isOpenSetter(originalScope, isOpen);
};

scope.select = function(activeIdx) {
//called from within the $digest() cycle
var locals = {};
Expand Down Expand Up @@ -463,7 +471,8 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
active: '=',
position: '&',
moveInProgress: '=',
select: '&'
select: '&',
assignIsOpen: '&',
},
replace: true,
templateUrl: function(element, attrs) {
Expand All @@ -472,8 +481,10 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
link: function(scope, element, attrs) {
scope.templateUrl = attrs.templateUrl;

scope.isOpen = function() {
return scope.matches.length > 0;
scope.isOpen = function () {
var isDropdownOpen = scope.matches.length > 0;
scope.assignIsOpen({ isOpen: isDropdownOpen });
return isDropdownOpen;
};

scope.isActive = function(matchIdx) {
Expand Down

0 comments on commit 167cfad

Please sign in to comment.