I am using Angular JS - ui.bootstrap.typeahead:
I would like to click a button and focus an input field and automatically show the typeahead suggestion dropdown. I h
I wanted something like the OP's description and the only solution I found was to come up with a template that combines the dropdown and typeahead directives - maybe the OP or someone else will find it useful:
angular.module('app', ['ui.bootstrap'])
.controller('AppCtrl', function($scope) {
$scope.model;
$scope.options = [{label:'Option 1'}, {label:'Option 2'}, {label:'Option 3'}];
$scope.onSelect = function($item, $model, $label) {
$scope.model = angular.copy($item);
}
});
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.12.0/ui-bootstrap-tpls.min.js"></script>
<div ng-app='app' style='padding:10px'>
<div ng-controller='AppCtrl'>
<div class='dropdown' dropdown style='width:200px'>
<!-- This needs UI Bootstrap 0.12 to work -->
<div class='input-group'>
<input type='text' class='form-control' ng-model='model.label' typeahead="op.label for op in options | filter:$viewValue | limitTo:8" typeahead-editable='false' />
<span class='input-group-btn'>
<button class='btn btn-default dropdown-toggle' dropdown-toggle>
<span class='caret'></span>
</button>
</span>
</div>
<ul class="dropdown-menu" role='menu' style='max-height:200px;overflow-y:scroll'>
<li ng-repeat='op in options'>
<a href ng-click='onSelect(op)'>{{op.label}}</a>
</li>
</ul>
</div>
</div>
</div>
Of course, you could simplify it to make the options just an array of strings- I made them objects because that was more like what I needed.
What we'd want is to trigger('input') on the input element when it's focused.
The correct way to do it in Angular is to do it in a directive.
angular.module('app')
.directive('showList', function() {
return {
restrict: 'A',
link: function(scope, iEle) {
iEle.focus(function() {
iEle.trigger('input');
});
}
};
});
Use this directive on the typeahead input element -
<input show-list uib-typeahead="state for state in states | filter:$viewValue" typeahead-min-length="0" class="form-control">
As HarishR mentioned in a comment, there is no built-in support for this feature yet.
But I just want to try hacking around and here is the result: http://plnkr.co/edit/Qrnat8yTvISuM1qHHDlA?p=preview
It contains a lot of hacks to make it works:
a custom empty-typeahead directive that interact with the ngModel's controller for applying the secretEmptyKey logic to bypass typeahead-min-length check:
.directive('emptyTypeahead', function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, modelCtrl) {
// this parser run before typeahead's parser
modelCtrl.$parsers.unshift(function (inputValue) {
var value = (inputValue ? inputValue : secretEmptyKey); // replace empty string with secretEmptyKey to bypass typeahead-min-length check
modelCtrl.$viewValue = value; // this $viewValue must match the inputValue pass to typehead directive
return value;
});
// this parser run after typeahead's parser
modelCtrl.$parsers.push(function (inputValue) {
return inputValue === secretEmptyKey ? '' : inputValue; // set the secretEmptyKey back to empty string
});
}
}
})
a custom filter comparator function that always return true (show all results) when one argument is the secretEmptyKey:
$scope.stateComparator = function (state, viewValue) {
return viewValue === secretEmptyKey || (''+state).toLowerCase().indexOf((''+viewValue).toLowerCase()) > -1;
};
remove the limitTo filter to show all results
Done!
typeahead-min-length="0" does the trick (I am using v0.4.0)
I wanted the typeahead to open whenever my input element had focus. @yohairosen's solution didn't work for me on the latest version of Angular Bootstrap (Version: 1.0.3). Here's the solution that worked for me. It involved manually invoking the parser attached by ui-bootstrap-typeahead which populates the suggestions:
angular.module('app')
.directive('typeaheadFocus', function () {
return {
require: 'ngModel',
link: function (scope, element, attr, ngModel) {
element.bind('click', function () {
ngModel.$parsers[0](ngModel.$viewValue);
});
}
};
};
});
This might be buggy because it assumes the parser added by ui-bootstrap-typeahead is the only one.
I got a working solution by changing some code in ui-bootstrap-tpls-0.10.0.js. So there are no differences in the typeahead html markup.
You can have a look here at http://plnkr.co/edit/LXHDpL?p=preview.
To use this fix, use the ui-bootstrap-tpls-0.10.0.js from the Plunk. To see my changes, open ui-bootstrap-tpls-0.10.0.js from the Plunk and search for 'ahneo'.
1. //minimal no of characters that needs to be entered before typeahead
kicks-in
// ahneo :: before
//var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;
// ahneo :: after (changed minimal no of characters to 0 by default)
var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 0;
2. // ahneo :: new (set input value to empty string if it contains " " string value)
if (inputValue === ' ') {
inputValue = '';
modelCtrl.$setViewValue('');
}
3. // ahneo :: before
//if (inputValue && inputValue.length >= minSearch) {
// ahneo :: after (add new condition to get matches for min search = 0)
if (minSearch === 0 || inputValue && inputValue.length >= minSearch) {
4. // ahneo :: new (bind element to focus event to trigger modelCtrl.$parsers.unshift method)
element.bind('focus', function (evt) {
if (modelCtrl.$viewValue === '') {
modelCtrl.$setViewValue(' ');
}
});
Hope this helps