11

检查这个PLNKR,我已经实现了预输入控制,默认情况下,在预输入控制中,它们没有设置任何最大高度或高度来列出,但根据要求,我必须将列表的高度固定为 110 像素。因此,当我们一次有更长的列表时,只会显示 4 个数据,并且可以通过向下滚动查看其余数据。当用户单击向上/向下滚动箭头时,滚动正在工作,但它不适用于键盘向上/向下键。

问题分步骤解释:-

  1. 键入一些东西,即“a”以获取预先输入的数据(将填充列表)
  2. 按向下箭头键(焦点将在列表项上)
  3. 按向下箭头键 4-5 次以进一步向下(当我们向下遍历列表时,滚动不会移动。)
  4. 它始终显示列表中的前 4 个项目。理想的行为是它应该转变。

用户可以通过手动单击滚动来滚动,但使用箭头键它不会滚动。

类型

HTML

<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
 <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
 <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.js"></script>
 <script src="example.js"></script>
 <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
 <link href="style.css" rel="stylesheet">
</head>
<body>
<div class='container-fluid' ng-controller="TypeaheadCtrl">
  <h4>Static arrays</h4>
  <pre>Model: {{selected | json}}</pre>
  <input type="text" ng-model="selected" typeahead="state for state in states | filter:$viewValue | limitTo:8" class="form-control">
 </div>
</body>
</html>

CSS

.dropdown-menu{
 height:110px;
 overflow:auto;
}

javascript 数据列表

$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'];
4

4 回答 4

9

这是工作的小插曲

在此,我已按照答案中的建议覆盖 ui-bootstrap typeahead 。

以下是我需要使其工作的更改:

在指令中添加了以下行typeaheadMatch(plunker 中 ui.bootstrap.typeahead.js 文件的第 335 行)

element[0].focus();

添加shouldFocus指令(行 - 314 -350)

.directive('shouldFocus', function(){
  return {
   restrict: 'A',
   link: function(scope,element,attrs){
     scope.$watch(attrs.shouldFocus,function(newVal,oldVal){
       element[0].scrollIntoView(false);
     });
   }
 };
})

最后在li(第 372 行)中添加指令

should-focus=\"isActive($index)\"
于 2015-01-13T17:24:28.607 回答
5

@user1690588 答案效果很好。唯一的问题是,当列表中的最后一项处于活动状态并且您按下向下键时。第一项的 scrollToView 不起作用。我添加了一项检查以确保 newVal 为真,这似乎解决了这个问题。

  if (newVal) { 
    element[0].scrollIntoView(false);
  }

http://plnkr.co/edit/05yoHSlhvX740tgiRRXm

于 2015-04-21T16:08:09.410 回答
3

我使用了另一种方法来解决这个问题,因为这里没有一个令人满意的解决方案。主要是:

  • 到达最后一个项目并按下 DOWN 键应该可以看到第一个项目
  • 用光标悬停的项目不应使 Typeahead 弹出窗口滚动
  • 使用鼠标滚轮不应触发 Typeahead 弹出窗口上的奇怪行为
  • 修复应避免修改 AngularUI Bootstrap 源

扩展 AngularUI Bootstrap 指令并仅监听特定的关键事件似乎提供了一种更简洁的解决方法,您可以在此处看到: http ://plnkr.co/edit/QuZw7j?p=preview

angular.module('ui.bootstrap.demo')
    .directive('typeahead', function () {
        return {
            restrict: 'A',
            priority: 1000, // Let's ensure AngularUI Typeahead directive gets initialized first!
            link: function (scope, element, attrs) {
                // Bind keyboard events: arrows up(38) / down(40)
                element.bind('keydown', function (evt) {
                    if (evt.which === 38 || evt.which === 40) {
                        // Broadcast a possible change of the currently active option:
                        // (Note that we could pass the activeIdx value as event data but AngularUI Typeahead directive
                        //  has its own local scope which makes it hard to retrieve, see:
                        //  https://github.com/angular-ui/bootstrap/blob/7b7039b4d94074987fa405ee1174cfe7f561320e/src/typeahead/typeahead.js#L104)
                        scope.$broadcast('TypeaheadActiveChanged');
                    }
                });
            }
        };
    }).directive('typeaheadPopup', function () {
        return {
            restrict: 'EA',
            link: function (scope, element, attrs) {
                var unregisterFn = scope.$on('TypeaheadActiveChanged', function (event, data) {
                    if(scope.activeIdx !== -1) {
                        // Retrieve active Typeahead option:
                        var option = element.find('#' + attrs.id + '-option-' + scope.activeIdx);
                        if(option.length) {
                            // Make sure option is visible:
                            option[0].scrollIntoView(false);
                        }
                    }
                });

                // Ensure listener is unregistered when $destroy event is fired:
                scope.$on('$destroy', unregisterFn);
             }
        };
    });

使用 AngularJS 1.4.5 和 AngularUI Bootstrap 0.13.4 进行测试,但这应该适用于其他最新版本。

[请注意,我必须手动包含 jQuery,因为 Plunker (jQuery v1.8.3) 预加载的 jQuery 将无法检索当前的活动选项。]

于 2015-10-06T10:05:43.887 回答
0

如果主窗口已经在滚动,则接受的解决方案将失败。@user1690588 是在正确的轨道上。

编辑 ui-bootstrap-tpls-0.13.3.js 并将其放在.filter('typeaheadHighlight')上方的第 5205 行附近,至少直到 AngularUI 团队决定修复此问题。以及将其他更改应用于已接受的解决方案引用的模板。

.directive('shouldFocus', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            scope.$watch(attrs.shouldFocus, function (newVal, oldVal) {
                if (newVal && element.prop("class").indexOf("active")) {
                    var par = element.parent("ul");
                    var scrollingTo = element.offset().top - par.offset().top + par.scrollTop();
                    // uncomment below section if you want the selected content to be 
                    // viewed at half the box height
                    // scrollingTo = scrollingTo - (par.height() / 2); 
                    par.scrollTop(scrollingTo);
                }
            });
        }
    }
})

此外,如果您想摆脱鼠标工件,它开始向上滚动直到它到达第一个条目或向下滚动直到到达最后一个条目,然后从模板中删除ng-mouseenter属性。

于 2015-09-08T18:05:08.033 回答