Filtering by Multiple Specific Model Properties in AngularJS (in OR relationship)

前端 未结 13 2399
北恋
北恋 2020-11-22 17:08

Take a look at the example here: http://docs.angularjs.org/api/ng.filter:filter

You can search by any of the phone properties by using

相关标签:
13条回答
  • 2020-11-22 17:58

    I like to keep is simple when possible. I needed to group by International, filter on all the columns, display the count for each group and hide the group if no items existed.

    Plus I did not want to add a custom filter just for something simple like this.

            <tbody>
                <tr ng-show="fusa.length > 0"><td colspan="8"><h3>USA ({{fusa.length}})</h3></td></tr>
                <tr ng-repeat="t in fusa = (usa = (vm.assignmentLookups | filter: {isInternational: false}) | filter: vm.searchResultText)">
                    <td>{{$index + 1}}</td>
                    <td ng-bind-html="vm.highlight(t.title, vm.searchResultText)"></td>
                    <td ng-bind-html="vm.highlight(t.genericName, vm.searchResultText)"></td>
                    <td ng-bind-html="vm.highlight(t.mechanismsOfAction, vm.searchResultText)"></td>
                    <td ng-bind-html="vm.highlight(t.diseaseStateIndication, vm.searchResultText)"></td>
                    <td ng-bind-html="vm.highlight(t.assignedTo, vm.searchResultText)"></td>
                    <td ng-bind-html="t.lastPublished | date:'medium'"></td>
                </tr>
            </tbody>
            <tbody>
                <tr ng-show="fint.length > 0"><td colspan="8"><h3>International ({{fint.length}})</h3></td></tr>
                <tr ng-repeat="t in fint = (int = (vm.assignmentLookups | filter: {isInternational: true}) | filter: vm.searchResultText)">
                    <td>{{$index + 1}}</td>
                    <td ng-bind-html="vm.highlight(t.title, vm.searchResultText)"></td>
                    <td ng-bind-html="vm.highlight(t.genericName, vm.searchResultText)"></td>
                    <td ng-bind-html="vm.highlight(t.mechanismsOfAction, vm.searchResultText)"></td>
                    <td ng-bind-html="vm.highlight(t.diseaseStateIndication, vm.searchResultText)"></td>
                    <td ng-bind-html="vm.highlight(t.assignedTo, vm.searchResultText)"></td>
                    <td ng-bind-html="t.lastPublished | date:'medium'"></td>
                </tr>
            </tbody>
    
    0 讨论(0)
  • 2020-11-22 17:58

    Here's simple solution for those who want a quick filter against an object:

    <select>
      <option ng-repeat="card in deck.Cards | filter: {Type: 'Face'}">{{card.Name}}</option>
    </select>
    

    The array filter lets you mimic the object you are trying to filter. In the above case, the following classes would work just fine:

    var card = function(name, type) {
      var _name = name;
      var _type = type;
    
      return {
        Name: _name,
        Type: _type
      };
    };
    

    And where the deck might look like:

    var deck = function() {
      var _cards = [new card('Jack', 'Face'),
                    new card('7', 'Numeral')];
    
      return {
        Cards: _cards
      };
    };
    

    And if you want to filter multiple properties of the object just separate field names by a comma:

    <select>
      <option ng-repeat="card in deck.Cards | filter: {Type: 'Face', Name: 'Jack'}">{{card.Name}}</option>
    </select>
    

    EDIT: Here's a working plnkr that provides an example of single and multiple property filters:

    http://embed.plnkr.co/i0wCx6l1WPYljk57SXzV/

    0 讨论(0)
  • 2020-11-22 17:59

    I might be very late but this is what I ended up doing. I made a very general filter.

    angular.module('app.filters').filter('fieldFilter', function() {
            return function(input, clause, fields) {
                var out = [];
                if (clause && clause.query && clause.query.length > 0) {
                    clause.query = String(clause.query).toLowerCase();
                    angular.forEach(input, function(cp) {
                        for (var i = 0; i < fields.length; i++) {
                            var haystack = String(cp[fields[i]]).toLowerCase();
                            if (haystack.indexOf(clause.query) > -1) {
                                out.push(cp);
                                break;
                            }
                        }
                    })
                } else {
                    angular.forEach(input, function(cp) {
                        out.push(cp);
                    })
                }
                return out;
            }
    
        })
    

    Then use it like this

    <tr ng-repeat-start="dvs in devices |  fieldFilter:search:['name','device_id']"></tr>
    

    Your search box be like

    <input ng-model="search.query" class="form-control material-text-input" type="text">
    

    where name and device_id are properties in dvs

    0 讨论(0)
  • 2020-11-22 18:00

    You can pass an Object as the parameter to your filter expression, as described in the API Reference. This object can selectively apply the properties you're interested in, like so:

    <input ng-model="search.name">
    <input ng-model="search.phone">
    <input ng-model="search.secret">
    <tr ng-repeat="user in users | filter:{name: search.name, phone: search.phone}">
    

    Here's a Plunker

    Heads up...this example works great with AngularJS 1.1.5, but not always as well in 1.0.7. In this example 1.0.7 will initialize with everything filtered out, then work when you start using the inputs. It behaves like the inputs have non-matching values in them, even though they start out blank. If you want to stay on stable releases, go ahead and try this out for your situation, but some scenarios may want to use @maxisam's solution until 1.2.0 is released.

    0 讨论(0)
  • 2020-11-22 18:04

    There are a bunch of good solutions here but I'd suggest going the other route with this. If searching is the most important thing and the 'secret' property is not used on the view at all; my approach for this would be to use the built-in angular filter with all its benefits and simply map the model to a new array of objects.

    Example from the question:

    $scope.people = members.map(function(member) { 
                                  return { 
                                    name: member.name, 
                                    phone: member.phone
                                  }});
    

    Now, in html simply use the regular filter to search both these properties.

    <div ng-repeat="member in people | filter: searchString">
    
    0 讨论(0)
  • 2020-11-22 18:05

    I inspired myself from @maxisam's answer and created my own sort function and I'd though I'd share it (cuz I'm bored).

    Situation I want to filter through an array of cars. The selected properties to filter are name, year, price and km. The property price and km are numbers (hence the use of .toString). I also want to control for uppercase letters (hence .toLowerCase). Also I want to be able to split up my filter query into different words (e.g. given the filter 2006 Acura, it finds matches 2006 with the year and Acura with the name).

    Function I pass to filter

            var attrs = [car.name.toLowerCase(), car.year, car.price.toString(), car.km.toString()],
                filters = $scope.tableOpts.filter.toLowerCase().split(' '),
                isStringInArray = function (string, array){
                    for (var j=0;j<array.length;j++){
                        if (array[j].indexOf(string)!==-1){return true;}
                    }
                    return false;
                };
    
            for (var i=0;i<filters.length;i++){
                if (!isStringInArray(filters[i], attrs)){return false;}
            }
            return true;
        };
    
    0 讨论(0)
提交回复
热议问题