Hol*_*ley 34 angularjs angular-ui-bootstrap
我正在使用Angular JS - ui.bootstrap.typeahead:
我想单击一个按钮并聚焦输入字段并自动显示预先输入建议下拉列表.我有一个指令,当单击按钮时自动聚焦输入字段.如何自动显示下拉列表,以便用户可以使用向下箭头或单击,以快速选择用户?
我创建了一个带有ui-bootstrap JS文件的Plunker,可以修改:
http://plnkr.co/edit/Z79LY0OYlwFc3wirjxol?p=preview
这是我的完整脚本:
<!doctype html>
<html ng-app="plunker">
<head>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.2/angular.js"></script>
<script src="ui-bootstrap-tpls-0.10.0.js"></script>
</head>
<body>
<script>
angular.module('plunker', ['ui.bootstrap'])
.directive('focusMe', function($timeout, $parse) {
return {
//scope: true, // optionally create a child scope
link: function(scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function(value) {
if(value === true) {
$timeout(function() {
element[0].focus();
});
}
});
}
};
});
function TypeaheadCtrl($scope, $http) {
$scope.selected = undefined;
$scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];
$scope.opened = false;
$scope.open = function() {
$scope.opened = true;
}
$scope.close = function() {
$scope.opened = false;
}
}
</script>
<div class='container-fluid' ng-controller="TypeaheadCtrl">
<h4>How can I open the typeahead dropdown automatically when button is pressed?</h4>
<p>I have a directive that automatically focuses on the field but I can't seem to automatically show the typeahead. Even adding down arrow key click support would be great.
<br/><br/>
<button class="btn btn-default" ng-show="!opened" ng-click="open()">Open Input and show typeahead!</button>
<button class="btn btn-default" ng-show="opened" ng-click="close()">Close Input</button>
<br/><br/>
<input type="text"
focus-me="opened"
ng-show="opened"
ng-model="selected"
typeahead="state for state in states | filter:$viewValue | limitTo:8"
class="form-control">
<br/>
<pre ng-show="opened">Model: {{selected | json}}</pre>
</div>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
yoh*_*sen 55
我将指令添加到github以便于更新和访问.您现在可以通过bower将其安装为依赖项.
我想出了一个漂亮干净的黑客工具,并没有要求任何修改UI的自举TPLS.想法是使用$ setViewValue()来通过特殊过滤器比较器功能的组合来触发弹出窗口.
为了绕过minLength检查,$ setViewValue()必须设置为大于1的值,所以我使用一个空格字符串.比较器功能的作用是将一个空格视为与所有项目匹配,这样在点击空输入时它们都会显示出来.
我创建了一个简单的指令:
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;
};
}
};
});
Run Code Online (Sandbox Code Playgroud)
用法:
<input type="text" ng-model="selected" typeahead="item for item in items | filter:$viewValue:emptyOrMatch | limitTo:8" typeahead-focus >
Run Code Online (Sandbox Code Playgroud)
run*_*arm 21
正如HarishR在评论中提到的那样,此功能尚无内置支持.
但我只想尝试黑客攻击,结果如下:http://plnkr.co/edit/Qrnat8yTvISuM1qHHDlA?p = preview
它包含许多黑客,使其工作:
一个自定义的empty-typeahead指令,它与ngModel的控制器交互,用于应用secretEmptyKey逻辑来绕过typeahead-min-length检查:
.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
});
}
}
})
Run Code Online (Sandbox Code Playgroud)一个自定义过滤器比较器函数,当一个参数是secretEmptyKey时,它始终返回true(显示所有结果):
$scope.stateComparator = function (state, viewValue) {
return viewValue === secretEmptyKey || (''+state).toLowerCase().indexOf((''+viewValue).toLowerCase()) > -1;
};
Run Code Online (Sandbox Code Playgroud)删除limitTo过滤器以显示所有结果
完成!
Hen*_*Neo 12
我通过更改ui-bootstrap-tpls-0.10.0.js中的一些代码得到了一个有效的解决方案.因此,typeahead html标记没有区别.
您可以在http://plnkr.co/edit/LXHDpL?p=preview查看.
要使用此修复程序,请使用Plunk中的ui-bootstrap-tpls-0.10.0.js.要查看我的更改,请从Plunk中打开ui-bootstrap-tpls-0.10.0.js并搜索"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(' ');
}
});
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助
现在,由于我没有足够的声誉来评论,我必须写一个新的答案,警告人们关于runTarm的答案.这是一个可行的解决方案,但它存在遇到以下错误的风险:
Error: [$rootScope:inprog] $apply already in progress
Run Code Online (Sandbox Code Playgroud)
这似乎是由于ng-focus是一个同步事件(见这里的讨论).相反,可以使用ng-click-attribute,并且不会发生此错误.
另外,我已经证实了这一点
$element.triggerHandler('input');
Run Code Online (Sandbox Code Playgroud)
与runTarm的答案中的jQuery触发器一样好用.
似乎内置的对此功能的支持即将在即将发布的版本中以typeahead-min-length属性支持值0 的形式出现.
它在主分支https://github.com/angular-ui/bootstrap/commit/d859f42cc022a5d8779f1c7b358486bbdd04ed57中的这个提交中实现,但是还没有发布它并且它不在0.14.x分支中.
希望新版本能够快速发布,以便不再需要这些变通方法.
| 归档时间: |
|
| 查看次数: |
52174 次 |
| 最近记录: |