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

feat(typeahead): add 'is-toggled' option #4779

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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-toggled` <i class="glyphicon glyphicon-eye-open"></i>
_(Defaults: angular.noop)_ :
Binding to a variable that indicates if dropdown is toggled
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-toggle indicator', function () {
var element;

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

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

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

it('should bind is-toggled indicator as false when a match is clicked', function () {
expect($scope.isToggled).toBeFalsy();
changeInputValueTo(element, 'b');
expect($scope.isToggled).toBeTruthy();
var match = $(findMatches(element)[1]).find('a')[0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to do var match = findMatches(element).find('a').eq(0)


$(match).click();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the above change, should be able to do just match.click()

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

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

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

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

it('should bind is-toggled 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-toggled="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 toggled
var isToggledSetter = $parse(attrs.typeaheadIsToggled).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-toggled': 'assignToggled(toggled)'
});
//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.assignToggled = function (toggled) {
isToggledSetter(originalScope, toggled);
};

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: '&',
assignToggled: '&',
},
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 toggled = scope.matches.length > 0;
scope.assignToggled({ toggled: toggled });
return toggled;
};

scope.isActive = function(matchIdx) {
Expand Down