проблема со стрелкой вверх/вниз с управлением вводом текста (угловой пользовательский интерфейс начальной загрузки)

Проверьте это PLNKR, я внедрил элемент управления typeahead. По умолчанию в элементе управления typeahead они не устанавливают максимальную высоту или высоту для списка, но согласно требованию я должен зафиксировать высоту списка до 110 пикселей. Итак, когда у нас есть более длинный список за раз, будут показаны только 4 данных, а остальные можно увидеть, прокрутив вниз. Прокрутка работает, когда пользователь нажимает стрелки вверх/вниз, но не работает с клавишами вверх/вниз на клавиатуре.

Проблема объясняется по шагам: -

  1. Введите что-нибудь, например, «a», чтобы получить данные в виде (список будет заполнен)
  2. Нажмите клавишу со стрелкой вниз (фокус будет на элементе списка)
  3. Нажмите клавишу со стрелкой вниз 4–5 раз, чтобы перейти вниз (когда мы перемещаемся вниз к списку, прокрутка не перемещается).
  4. Он всегда показывает первые 4 элемента в списке. Идеальное поведение - оно должно смещаться.

Пользователь может прокручивать, нажимая на прокрутку вручную, но с помощью клавиши со стрелкой он не прокручивается.

Введите a и перейдите вниз к списку, при этом прокрутка со стрелкой вниз не работает.

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

person ankitd    schedule 30.12.2014    source источник
comment
для меня это работает (хром)   -  person maioman    schedule 30.12.2014
comment
@maioman m использует Chrome (версия 39.0.2171.95 m), он не работает.   -  person ankitd    schedule 30.12.2014
comment
Я ошибался, это не так - проверьте $anchorScroll   -  person maioman    schedule 30.12.2014
comment
@ user1690588 согласен, при задании вопроса он не отображался в списке ранее заданных вопросов. Но ответ, данный там, бесполезен.   -  person ankitd    schedule 13.01.2015
comment
Вчера я также столкнулся с проблемой, о которой вы упоминаете в своем посте, и ссылка мне помогает. Я скоро обновлю ваш plunkr сегодня.   -  person MKB    schedule 13.01.2015
comment
@ user1690588 заранее спасибо .. жду plunkr. :-)   -  person ankitd    schedule 13.01.2015
comment
У кого-нибудь есть решение для этого, я борюсь с этим 3 дня.   -  person KanhuP2012    schedule 23.03.2015
comment
@KanhuP2012, см. мой ответ ниже (stackoverflow.com/questions/27705490/).   -  person almeidap    schedule 06.10.2015


Ответы (4)


Вот рабочий планкер

В этом я переопределяю тип ui-bootstrap, как это предлагается в ответ.

Ниже приведены изменения, которые мне нужны, чтобы заставить его работать:

Добавлена ​​следующая строка в директиве typeaheadMatch (строка - 335 файла ui.bootstrap.typeahead.js в плункере)

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)\"
person MKB    schedule 13.01.2015
comment
Это не работает, когда страница с прокруткой и элементом ввода немного ниже. Пожалуйста, помогите в этом. - person KanhuP2012; 23.03.2015
comment
@KanhuP2012 - Не могли бы вы создать плункер, демонстрирующий такое поведение? Это будет очень полезно для исправления ошибки. Спасибо - person MKB; 23.03.2015
comment
пожалуйста, найдите планк для этого plnkr.co/edit/qpkrmBVFNZSpxpC4eeJt?p=preview на выбор выпадающего вида главной страницы прокручивается назад. - person KanhuP2012; 23.03.2015
comment
@KanhuP2012 - Хорошо, у тебя есть решение, круто. Вы должны опубликовать это как ответ. - person MKB; 23.03.2015
comment
@MKB Привет, я столкнулся с той же проблемой, но с Angular 8.2 и ngx-bootstrap 4.1.1. Как мне решить это там? Спасибо - person RushabhG; 30.06.2020

Ответ @ user1690588 отлично работает. Единственная проблема в том, что когда последний элемент в списке активен и вы нажимаете клавишу вниз. scrollToView для первого элемента не работает. Я добавил проверку, чтобы убедиться, что newVal истинен, что, кажется, исправляет это.

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

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

person JimmyBob    schedule 21.04.2015

Я использовал другой подход для решения этой проблемы, так как ни одно из решений здесь не удовлетворяет. В основном:

  • Достигнув последнего элемента и нажав клавишу ВНИЗ, вы увидите первый элемент.
  • наведение курсора на элементы не должно вызывать прокрутку всплывающего окна 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), не сможет получить текущую активную опцию.]

person almeidap    schedule 06.10.2015
comment
Привет, я столкнулся с той же проблемой, но с Angular 8.2 и ngx-bootstrap 4.1.1. Как мне решить это там? Спасибо - person RushabhG; 06.07.2020

Принятое решение потерпит неудачу, если главное окно уже прокручивается. @user1690588 был на правильном пути.

Отредактируйте файл ui-bootstrap-tpls-0.13.3.js и поместите его в строке 5205 выше .filter('typeaheadHighlight'), по крайней мере, до тех пор, пока команда 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.

person ewahner    schedule 08.09.2015