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
you can achieve by this code
$scope.change = function() {
var e = document.getElementById("test");
var $e = angular.element(e);
$e.triggerHandler('focus');
$e.triggerHandler('input');
}
change the test to your type-head ID
Now, as I don't have enough reputation to comment, I must write a new answer to warn people about runTarm's answer above. This is a viable solution, but it runs the risk of running into the following error:
Error: [$rootScope:inprog] $apply already in progress
This seems to be due to ng-focus being a synchronized event (see discussion here). Instead, one can use the ng-click-attribute, and this error doesn't occur.
Also, I've verified that
$element.triggerHandler('input');
works just as good as the jQuery-trigger in runTarm's answer.
I got solved this issue through a directive. When you uses this directive, shows the list without some filter then, you type your search to find an element.
angular.module('myapp')
.directive('typeaheadLikeSelect',
['$parse',function($parse) {
return {
require: 'ngModel',
link: function (scope, element, attr, ngModel){
var aux_modelValue, aux_viewValue,
modelGetter = $parse(attr.ngModel),
modelSetter = modelGetter.assign;
var noViewValue = function(){
return
ngModel.$$lastCommittedViewValue === undefined ||
!ngModel.$$lastCommittedViewValue.trim();
};
var forceEvent = function(){
ngModel.$setViewValue();
ngModel.$viewValue = ' ';
ngModel.$setViewValue(' ');
ngModel.$render();
scope.$apply();
element.val(element.val().trim());
};
element.on('mousedown', function(e){
e.stopPropagation();
forceEvent();
});
element.on('blur', function(e){
e.stopPropagation();
if(aux_modelValue){
modelSetter(scope, aux_modelValue);
scope.$apply();
}
});
scope.$watch(function () {
return ngModel.$modelValue;
}, function(newValue, oldValue){
if(newValue || (!newValue && !oldValue))
aux_modelValue = newValue;
});
}
};
}]);
I leave a view code, to testing the above code.
<script type="text/ng-template" id="customTemplate.html">
<a>
<span ng-bind-html="match.label.description | uibTypeaheadHighlight:query"></span>
</a>
</script>
<div class="form-group has-feedback" ng-class="{'has-success':items.mymodel}">
<input
placeholder="typeahead"
ng-model="items.mymodel"
uib-typeahead="responses as responses for responses in getResponses($viewValue)"
typeahead-template-url="customTemplate.html"
typeahead-input-formatter="$model.description"
typeahead-loading="loadingResponses"
typeahead-no-results="noResponses"
typeahead-editable="false"
typeahead-on-select="changeItem($item)"
class="form-control"
required="required"
typeahead-like-select>
<div ng-show="noResponses">
<i class="glyphicon glyphicon-remove"></i> No Results Found
</div>
<span ng-show="!items.mymodel" class="glyphicon glyphicon-search form-control-feedback" aria-hidden="true"></span>
<span ng-show="items.mymodel" class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>
</div>
Seems like built-in support for this feature is coming in an upcoming release in the form of typeahead-min-length
attribute supporting value of 0.
It is implemented in this commit in the master branch https://github.com/angular-ui/bootstrap/commit/d859f42cc022a5d8779f1c7b358486bbdd04ed57, but there is no release with this yet and it's not in the 0.14.x branch.
Hopefully a new release will come quickly so that there is no need for these workarounds anymore.
I added the directive to github for easy updates and access. You can now install it as a dependency through bower.
I came up with a pretty clean hack that does not require any changes to ui-bootstrap-tpls. The Idea is to use $setViewValue() to trigger the popup with a combination of a special filter comparator function.
In order to bypass the minLength check, $setViewValue() has to be set to a value longer than 1 so i'm using one space string. The role of the comparator function is to treat one space as a match to all items so they'll all show up when clicking on an empty input.
I created a simple directive:
angular.module('app')
.directive('typeaheadFocus', function () {
return {
require: 'ngModel',
link: function (scope, element, attr, ngModel) {
//trigger the popup on 'click' because 'focus'
//is also triggered after the item selection
element.bind('click', function () {
var viewValue = ngModel.$viewValue;
//restore to null value so that the typeahead can detect a change
if (ngModel.$viewValue == ' ') {
ngModel.$setViewValue(null);
}
//force trigger the popup
ngModel.$setViewValue(' ');
//set the actual value in case there was already a value in the input
ngModel.$setViewValue(viewValue || ' ');
});
//compare function that treats the empty space as a match
scope.emptyOrMatch = function (actual, expected) {
if (expected == ' ') {
return true;
}
return actual.indexOf(expected) > -1;
};
}
};
});
Usage:
<input type="text" ng-model="selected" typeahead="item for item in items | filter:$viewValue:emptyOrMatch | limitTo:8" typeahead-focus >