Угловой фильтр по текстовому поиску и выпадающему списку

У меня проблемы, и я не могу найти ответ. Я пытаюсь фильтровать, используя поле ввода текста и раскрывающееся меню. Это приложение для фэнтези-футбола, чтобы дать вам представление. Некоторый код ниже

 <form class="form-inline search-width">
<input class="search form-control" type="text" ng-model="nameSearch.name">
<select class="form-control" ng-model="nameSearch.position">
    <option value="All">All</option>
    <option value="QB">QB</option>
    <option value="RB">RB</option>
    <option value="WR">WR</option>
    <option value="TE">TE</option>
    <option value="DEF">DEF</option>
    <option value="K">K</option>
</select>
    {{nameSearch.position}}
</form>
<ul class="list">

    <li ng-repeat="list in playerlist" 
        ng-click="PlayerSelected($event, this)">Rank: {{list.Rank}} Pos: {{list.Position}} {{list.Team}}</br>
        {{list.Last}}, {{list.First}} Bye: {{list.Bye}}</li>

</ul>

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


person jminterwebs    schedule 26.08.2015    source источник
comment
Можете ли вы также поделиться кодом JS для этого, или лучше будет скрипка.   -  person Venkata Krishna    schedule 26.08.2015
comment
уверен, что все это на github по адресу github.com/jminterwebs/DraftBoard, извините, пока не знаком со скрипкой.   -  person jminterwebs    schedule 26.08.2015


Ответы (6)


Пользовательский фильтр может быть полезен в вашей ситуации. Вот как бы я это решил.

Фильтр:

angular.module('DraftBoard').filter('playersFilter', function () {
    return function (input, filterObject) {
        if (filterObject == undefined) { return input; }

        var searchName = filterObject.name.toLowerCase();
        var searchPosition = filterObject.position.toLowerCase();
        var out = [];
        if (input != undefined) {
            for (var i = 0; i < input.length; i++) {

                var firstName = input[i].First != undefined ? input[i].First.toString().toLowerCase() : '';
                var lastName = input[i].Last != undefined ? input[i].Last.toString().toLowerCase() : '';
                var team = input[i].Team != undefined ? input[i].Team.toString().toLowerCase() : '';
                var position = input[i].Position != undefined ? input[i].Position.toString().toLowerCase() : '';

                var filterCondition = ((searchPosition === 'all') || (position.indexOf(searchPosition) > -1))
                    && ((searchName == '') || (firstName.indexOf(searchName) > -1) || (lastName.indexOf(searchName) > -1) || (team.indexOf(searchName) > -1));

                if (filterCondition) {
                    out.push(input[i]);
                }
            }
        }
        return out;
    };
});

В вашем контроллере добавьте это:

$scope.nameSearch = {
        name: '',
        position: 'All'
    };

И в представлении используйте его следующим образом:

<div class="selectionlist">
    <form class="form-inline search-width">
    <input class="search form-control" type="text" ng-model="nameSearch.name">
    <select class="form-control" ng-model="nameSearch.position">
        <option value="All">All</option>
        <option value="QB">QB</option>
        <option value="RB">RB</option>
        <option value="WR">WR</option>
        <option value="TE">TE</option>
        <option value="DEF">DEF</option>
        <option value="K">K</option>
    </select>
        {{nameSearch.position}}
    </form>
    <ul class="list">

        <li ng-repeat="list in playerlist | playersFilter:nameSearch "
            ng-click="PlayerSelected($event, this)">
            Rank: {{list.Rank}} Pos: {{list.Position}} {{list.Team}}</br>
            {{list.Last}}, {{list.First}} Bye: {{list.Bye}}
        </li>

    </ul>

</div>
person Dmitry Bogomolov    schedule 26.08.2015
comment
Это именно то, что я пытался сделать. Спасибо. Теперь осталось разобраться, как это все работает. - person jminterwebs; 27.08.2015
comment
@jminterwebs, приятно, что мой ответ вам помог. Итак, этот фильтр довольно прост: у вас есть два параметра (исходный массив input и критерии фильтра filterObject) в качестве входных параметров. Затем внутри функции фильтра вы выбираете некоторые элементы из исходного массива в зависимости от критериев фильтра и вашей бизнес-логики. А затем вернуть выбранные элементы в виде массива. - person Dmitry Bogomolov; 28.08.2015

Вы должны использовать параметр фильтра из ng-repeat, вот пример, который вы можете проверить, я надеюсь, что это поможет вам .

person Alejandro Garcia Anglada    schedule 26.08.2015
comment
Спасибо огромное улучшение. Еще немного глючит. Только позволит мне искать или или. В идеале я хочу установить раскрывающееся значение, а затем выполнить поиск по этому значению. - person jminterwebs; 26.08.2015
comment
В раскрывающемся списке есть модель, фильтр, он следит за изменениями его свойств, поэтому каждый раз, когда фильтр изменения модели будет реагировать, попробуйте изменить его непосредственно в контроллере, чтобы дать вам представление - person Alejandro Garcia Anglada; 26.08.2015

Здесь вы можете найти собственный фильтр для выпадающего списка и поиска

я надеюсь, что это код поможет с чем-то новым!

person Shasha    schedule 26.08.2015

вот моя попытка на этом http://jsfiddle.net/0ey84dwu/

HTML: используйте ng-repeat и отфильтруйте его по вводу текста. Также используйте ng-options

    <div ng-app="TestApp">
        <div ng-controller="TestController">
            <input class="search form-control" type="text" ng-model="nameSearch.name">
            <select class="form-control" ng-options="position as position for position in positions" ng-model="nameSearch.position" ng-change="setPosition()">
            </select>

            <div ng-repeat="player in players | filter: nameSearch.name">
               {{player.First}} {{player.Last}}
            </div>
        </div>
    </div>

И затем JS: Имейте массив всех игроков. В зависимости от вашего выбора в раскрывающемся списке добавьте этих игроков в новый массив, который содержит только игроков выбранной позиции. Выбор All установит $scope.players = $scope.allPlayers, таким образом фильтруя всех игроков по тому, что вы ищете.

var app = angular.module('TestApp',[]);

app.controller('TestController', function($scope)
{
  $scope.nameSearch = {};
  $scope.nameSearch.position = 'All';
  $scope.positions = ['All','QB','RB','WR','TE','DEF','K'];
  $scope.players = $scope.allPlayers;

  $scope.setPosition = function()
  {
    $scope.players = [];
    if ($scope.nameSearch.position != 'All')
    {
       for (var i in $scope.allPlayers) if ($scope.allPlayers[i].Position == $scope.nameSearch.position) $scope.players.push($scope.allPlayers[i]);   
       return;
     }
     $scope.players = $scope.allPlayers;
  };

  $scope.allPlayers = [
  {
    "Rank":1,
    "First":"Le'Veon",
    "Last":"Bell",
    "Position":"RB",
    "Team":"PIT",
    "Bye Week":11
  },
  {
    "Rank":2,
    "First":"Jamaal",
    "Last":"Charles",
    "Position":"RB",
    "Team":"KC",
    "Bye Week":9
  },
  {
    "Rank":3,
    "First":"Adrian",
    "Last":"Peterson",
    "Position":"RB",
    "Team":"MIN",
    "Bye Week":5
  }...
  ...
  ..
  ...];

  $scope.setPosition();

});

Вы можете написать собственный фильтр и еще больше сократить этот код.

person Ronnie    schedule 26.08.2015
comment
Как можно было бы сделать пользовательский фильтр. - person jminterwebs; 26.08.2015

Измените ng-model вашего <select> на nameSearch.Position (заглавная буква P), чтобы оно соответствовало имени поля позиции в списке игроков.

   <select class="form-control" ng-model="nameSearch.Position">

Затем измените второй фильтр ng-repeat на nameSearch вместо nameSearch.position.

 ng-repeat="list in playerlist | filter:searchname | filter: nameSearch"

Если у вас есть входные данные поиска с тем же именем, что и у атрибутов объекта (например: nameSearch.Position то же, что и playerlist.Position), фильтрация только по объекту фильтра (nameSearch) без атрибута фильтра (Position) будет искать сопоставление соответствующих атрибутов с тем же именем.

ОБНОВЛЕНИЕ: Вышеизложенное поможет вам исправить поиск в раскрывающемся списке "Позиция".
Для имени используйте настраиваемый фильтр, как показано ниже.
Обратите внимание, что searchname добавлен в качестве фильтра в ng-repeat и сохраните ваш поисковый запрос ng-model не является объектом. Для приведенного ниже контроллера вам придется оставить его как
<input class="search form-control" type="text" ng-model="nameSearch">

Контроллер:

$scope.searchname = function (row) {
        return (angular.lowercase(row.First).indexOf($scope.nameSearch || '') !== -1 || angular.lowercase(row.Last).indexOf($scope.nameSearch || '') !== -1);
    };

Надеюсь, это помогло.

person Venkata Krishna    schedule 26.08.2015

Плагин ui.bootstrap.typeahead может быть тем, что вам нужно:

http://angular-ui.github.io/bootstrap/

Скриншот: https://i.stack.imgur.com/VJenP.png< br>

Он добавляет атрибут uib-typeahead к тегу ‹input›.

Пример использования:

<input type="text" ng-model="customPopupSelected" 
    placeholder="Custom popup template" 
    uib-typeahead="state as state.name for state in statesWithFlags | filter:{name:$viewValue}" 
    typeahead-popup-template-url="customPopupTemplate.html" 
    class="form-control">

Цитаты из его документации:

Typeahead — это AngularJS-версия плагина Bootstrap v2 typeahead. Эта директива может быть использована для быстрого создания элегантных шрифтов с любой формой ввода текста.

Он очень хорошо интегрирован в AngularJS, поскольку использует подмножество синтаксиса директивы select, что очень гибко. Поддерживаемые выражения:

метка для значения в sourceArray выберите в качестве метки для значения в sourceArray Выражение sourceArray может использовать специальную переменную $viewValue, которая >соответствует значению, введенному внутри ввода.

Эта директива работает с промисами, то есть вы можете получать совпадения с помощью службы >$http с минимальными усилиями.

person gm2008    schedule 23.11.2017