2

I have an array of objects which I want to display as a table with filter. My filter with model name is filtering the deep object family. This works fine but not the way I want it to work...

What I want: Insert string to input, e.g. 'Ma'. Now, I want it to display all items containing a string in family matching 'Ma' - that means I want to keep all the family members displayed as long as one string matches. In my example this would be the filtered result:

Homer    Marge, Bart, Lisa, Maggie
Ned      Maude, Rod, Todd

Example Code with snippet below:

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

myApp.controller('MyCtrl', function($scope) {
    $scope.tableData = [
        {id: 1, name: 'Homer', family: ['Marge', 'Bart', 'Lisa', 'Maggie']},
        {id: 2, name: 'Carl', family: []},
        {id: 3, name: 'Lenny', family: []},
        {id: 4, name: 'Clancy', family: ['Sarah', 'Ralph']},
        {id: 5, name: 'Ned', family: ['Maude', 'Rod', 'Todd']},
        {id: 6, name: 'Moe', family: []}
    ];
});
table td {
    padding: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
    <table>
        <tr>
            Filter family members: <input type="text" ng-model="name">
        </tr>
        <tr ng-repeat="item in tableData">
            <td>{{item.name}}</td>
            <td>
                <span ng-repeat="member in item.family | filter: name">
                    {{member}}{{$last ? '' : ', '}}
                </span>
            </td>
        </tr>
    </table>
</div>
DonJuwe
  • 4,477
  • 3
  • 34
  • 59

4 Answers4

2

You need to filter the first ng-repeat:

<tr ng-repeat="item in tableData | filter: name && {family: name}">

The key is to provide the name of the property you want to filter on. Here it is the property family.

See fiddle (Type ma in the search box)

Edit: And remove the filter you placed on the inner ng-repeat

Michel
  • 26,600
  • 6
  • 64
  • 69
1

You want to use a custom filter on the top ng-repeat. You can specify a function as the filter: custom filter answer. In this custom filter return all items in tableData that contain a match in the sub array.

Note: You could use lodash to help with this calculation.

Example: plunkr example

<tr ng-repeat="item in tableData | filter:criteriaMatch(name)">

...

$scope.criteriaMatch = function( criteria ) {
    return function( item ) {
        if(!angular.isDefined(criteria) || criteria === "")
            return true;

        var results = _.filter(item.family, function(n) {
           if(_.contains(n.toUpperCase(), criteria.toUpperCase()))
           {
             return true;
           }
        });

        if(results.length !== 0)
          return true;

        else  return false;

    };
};
Community
  • 1
  • 1
trees_are_great
  • 3,881
  • 3
  • 31
  • 62
1

You can solve this without a custom filter, by providing a conditional filter on the first ng-repeat. For example:

<tr ng-repeat="item in tableData | filter: (name.length > 0 || '') && {family: name}">

You need the conditional because if you add a filter and remove it, the blank arrays wont be considered (angular quirk).

I have created a working fiddle here

Matt Way
  • 32,319
  • 10
  • 79
  • 85
-1

Do you try to use the filter in tableData?? Something like this:

<input type="text" ng-model="family">

And

<tr ng-repeat="item in tableData | filter: family">