Как изменить действие фильтра, когда нет ввода?

#javascript #angularjs #filter #angularjs-ng-repeat

#javascript #angularjs #Фильтр #angularjs-ng-repeat

Вопрос:

Я хочу создать заголовок типа в AngularJS, и, следуя этому руководству, я проделал большую часть пути. Единственное, чего он не делает для меня, это то, что я хочу, чтобы весь список отображался при первом щелчке в поле, вместо того, чтобы ожидать, пока ввод что-нибудь покажет.
В шаблоне он имеет

 <input type="text" ng-model="model" placeholder="{{prompt}}"
    ng-keydown="selected=false"/>
    ...
    <div class="item" ng-repeat="item in items | filter:model  track by $index" 
        ng-click="handleSelection(item[title])" style="cursor:pointer"
        ng-class="{active:isCurrent($index)}" ng-mouseenter="setCurrent($index)">
  

Мне нужно создать пользовательский фильтр, который, я полагаю, был бы похож на

 .filter('psudoFilter', function($filter){    
    var original_filter = $filter('filter');
    return function(input){
        if(input.length === 0){
            return // What should I return if I don't want to change the data?
        } else {
            return original_filter(input_to_filter_items_by); //Filter as usual
        }
    }    
}); 
  

Проблема, с которой я сталкиваюсь, заключается в том, что должна возвращать внутренняя функция, чтобы она не фильтровала при отсутствии ввода? как фильтр взаимодействует с данными, которые он фактически будет фильтровать?

Ответ №1:

Проблема на самом деле не в фильтре. Проблема в том, что список элементов виден только в том случае, если что-то введено в текстовое поле:

 <div class="items" ng-hide="!model.length || selected">
  

Что вы хотите сделать, это показать список при нажатии на текстовое поле. Я предполагаю, что вы также хотите скрыть список, когда текстовое поле теряет фокус. Добавьте ng-focus и ng-blur события в текстовое поле. Я устанавливаю boxHasFocus свойство в этих событиях и изменяю ng-hide в списке, чтобы оно отображало, когда boxHasFocus оно истинно.

 <input type="text" ng-model="model" placeholder="{{prompt}}" ng-keydown="selected=false" ng-focus="boxHasFocus=true" ng-blur="boxHasFocus=false" />
<br/>
<div class="items" ng-hide="(!model.length || selected) amp;amp; !boxHasFocus">
  

Однако с этим есть проблема. Изначально элементы списка выглядели так:

 <div class="item" ng-repeat="item in items | filter:model  track by $index" ng-click="handleSelection(item[title])" ...
  

Проблема в том, что blur событие срабатывает перед click событием, поэтому список исчезает до того, как он сможет зарегистрировать, что вы нажали на элемент. Решение состоит в том, чтобы использовать ng-mousedown вместо ng-click , потому mousedown что события запускаются перед blur событиями.

 <div class="item" ng-repeat="item in items | filter:model  track by $index" ng-mousedown="handleSelection(item[title])"
  

Вот демонстрация, показывающая, как это работает.

Комментарии:

1. Спасибо за хорошо объясненный ответ. Просто из любопытства, где вы нашли порядок событий наведения курсора мыши, затем размытия, а затем щелчка?

2. Я просто погуглил. На самом деле нет окончательной спецификации относительно порядка событий; каждый браузер может реализовать его по-разному (к сожалению).

Ответ №2:

Проверьте это. Единственная часть, которую этот пример не обрабатывает, — это отображение всего списка, когда пользователь нажимает на него для начала. Но это будет легко подключить.

http://www.byteblocks.com/Post/Autosuggest-text-box-using-AngularJS