Подтвердить что ты не робот

Строгий фильтр AngularJS только для одного поля

У меня есть форма с несколькими фильтрами, но для некоторых мне нужно строгое сравнение.

tl; dr: строгое сравнение для user_id не для firstname.

<select ng-model="search.user_id">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="10">10</option>
    <option value="11">11</option>
    <option value="23">23</option>
</select>

<input type="text" ng-model="search.firstname">

<ul>
    <li ng-repeat="user in users | filter:search">#{{ user.user_id }} {{ user.firstname}}</li>
</ul>

Я попробовал третий параметр true, но он также работает для фильтра firstname.

Проблема заключается в следующем: если вы выберете значение 2, все пользователи с 2 в своем id будут отфильтрованы, я не хочу этого поведения.

Вот fiddle.

4b9b3361

Ответ 1

Я попытался исправить его изначально, а не с помощью пользовательских фильтров, его работу, здесь PLUNKER LINK

должен был указать тег нескольких фильтров

<li ng-repeat="user in users | filter:{'user_id':  search.user_id}: true | filter: {'firstname' : search.firstname}">

хотя есть несколько предостережений:

  • Мне пришлось изменить тип из числа в строку...

  • если я reset значение точного соответствия не работает...

поэтому мне пришлось написать настраиваемый файл, который работает для точного соответствия и игнорирует пустые/нулевые значения

$scope.filter2 = function(field1, field2) {
  if(field2 === "" || field2 === null) return true;
  return field1 === field2;
};

вы нашли бы их обоих в предоставленной ссылке plunker

Ответ 2

У вас может быть такая функция в вашем контроллере

$scope.identical = function(actual, expected){
    return actual === parseInt(expected);
}

а затем вы можете использовать его следующим образом

<li ng-repeat="user in users | filter:search.user_id:identical">

Ответ 3

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

Я использовал решение HarisR, но я его модифицировал, чтобы его можно было использовать с числами, если вам нужно ваше значение как число.

$scope.filter2 = function(field1, field2) {
  if(field2 === "" || field2 === null) return true;
  return field1.toString() === field2;
};

или

$scope.filter2 = function(field1, field2) {
  if(field2 === "" || field2 === null) return true;
  return ""+field1 === field2;
};

Ответ 4

Я столкнулся с этой проблемой, когда загрузил некоторую конфигурацию формы из Json, и числа были переданы inn как число, а не String.

<div ng-repeat="selectedComponent from ctrl.drivers.components |
     filter:{
             manufacturer: component.manufacturer, 
             type: component.type}:true">

Когда у меня был тип компонента 1 и 10, оба появлялись бы в моем ng-repeat, прежде чем я добавил :true к моему фильтру, и ничего, если бы я добавил строгое равенство.

Чтобы исправить это, я добавил метод к моему контроллеру под названием castToInt

ctrl.castToInt = function(value){
    return parseInt(value);
};

Затем я изменил свой фильтр, чтобы показать

<div ng-repeat="selectedComponent from ctrl.drivers.components |
     filter:{
             manufacturer: component.manufacturer, 
             type: ctrl.castToInt(component.type)}:true">

Voila, тогда все это работало

Я предполагаю, что :true обеспечивает строгое равенство ===, поэтому вы получите ложь, если вы сравниваете разные типы.

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

- Томас

Ответ 5

Измените свой html:

<li ng-repeat="user in users | filter:f">#{{ user.user_id }} {{ user.firstname}}</li>

Я предполагаю, что вы хотите and, если присутствуют оба значения. При необходимости измените его на or. Пользовательская функция фильтра:

$scope.f = function(val) {
    var hasUserId = $scope.search.user_id;
    var hasName = $scope.search.firstname;

    var firstNameMatch = function() { return val.firstname.indexOf($scope.search.firstname) > -1 };
    var userIdMatch = function() { return $scope.search.user_id == val.user_id };

    if(hasUserId && hasName) {
       return  firstNameMatch() && userIdMatch()
    } else if (hasUserId) {
        return userIdMatch();
    } else if (hasName) {
        return firstNameMatch();
    }
    return true;
};

Еще одно изменение вашего контроллера:

$scope.search= {};

Forked Fiddle.

Ответ 6

Если вы хотите искать по имени, например, просто добавьте текстовое поле с name= search.yourFieldNameToName, если вы хотите искать во всех полях, просто создайте текстовое поле с поиском. $, а затем просто добавьте фильтр: search: strict on ваша директива ng-repeat.

Пример кода Чтобы лучше объяснить:

<div class="customers view">
<div class="container">
    <header>
        <h3>Customers</h3>
    </header>
    <div class="row">
        <div class="span3">
            Search All:
            <input data-ng-model="search.$" type="text" placeholder="All Search" />
        </div>
        <div class="span3">
            Search By Name: 
            <input data-ng-model="search.firstName" type="text" placeholder="First Name Search" />
        </div>
        <div class="span3">
            Search By LastName:
            <input data-ng-model="search.lastName" type="text" placeholder="Last Name Search" />                
        </div>
        <div class="span3">
            Search By City:
            <input data-ng-model="search.city" type="text" placeholder="City Search" />
        </div>

    </div>
    <div>
        <div class="row cardContainer">
            <div class="span3 card" data-ng-repeat="customer in customers | filter:search:strict | orderBy:'firstName'">
                <button class="btn close cardClose" data-ng-click="deleteCustomer(customer.id)">&times;</button>
                <div class="cardHeader">{{customer.firstName + ' ' + customer.lastName}}</div>
                <div class="cardBody">{{customer.city}}</div>
                <a href="#/customerorders/{{customer.id}}" class="cardBody btn-link">View {{ customer.orders.length }} Orders</a>
            </div>
        </div>
    </div>
</div>