pertrai1
pertrai1

Reputation: 4318

How to ng-repeat multiple properties?

I have taken the example from Angular documentation into a Plunker for a quick demonstration of what I am trying to do. What I have is a name and lastName as part of an object in array. When I start to filter the input, it works well until I start to type the lastName after I have typed the name. How would I go about having it so that the search results would include the name and the lastName? I have been stumped on this and can't get past figuring this out so I am looking for a little help.

<div ng-controller="repeatController">
  I have {{friends.length}} friends. They are:
  <input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />

  <ul class="example-animate-container">
    <li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
      [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
    </li>
    <li class="animate-repeat" ng-if="results.length === 0">
      <strong>No results found...</strong>
    </li>
 </ul>
</div>

Here is the Plunker: https://plnkr.co/edit/SS2X2ZmguxNxQ4Txz3BN

Thank you in advance for any help given.

EDIT: What I am looking for is that if I was to type John Doe, the result would not say "No results found". It works fine if I am typing in one property, but once I start to do the lastName, there are no results found.

Upvotes: 1

Views: 370

Answers (3)

Frederik Prijck
Frederik Prijck

Reputation: 1509

To show the lastName, you can do the exact same thing as you're doing with both the friend's name and age.

<li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
      [{{$index + 1}}] {{friend.name}} {{friend.lastName}} who is {{friend.age}} years old.
</li>

I've updated your plunkr: https://plnkr.co/edit/gocfrflA6VKUDBwBcYKK?p=preview

Edit: As you're also interested to search over a combination of multiple fields, you need to implement a custom filter function.

$scope.search = function (friend) {
  var fullName = friend.name + ' ' + friend.lastName;
  return !$scope.q || fullName.indexOf($scope.q) !== -1;
};

and

<li class="animate-repeat" ng-repeat="friend in friends | filter: search">

I've created a plunkr for this aswell: https://plnkr.co/edit/fr3XH3ghMw0hidceXDVx?p=preview

An even better approach would be to make use of a custom filter. Be sure to read: https://toddmotto.com/everything-about-custom-filters-in-angular-js/ and https://docs.angularjs.org/guide/filter

Upvotes: 3

maksbd19
maksbd19

Reputation: 3830

In another approach I'd like to modify the list which I'm iterating, friends in your case.

<input type="search" ng-model="q" placeholder="filter friends..." aria-label="filter friends" />
<ul class="example-animate-container">

    <!-- instead of using the list directly I'd like to call a function which would return me the filtered list, hence getFriends()-->

    <li class="animate-repeat" ng-repeat="friend in getFriends()">
      [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
    </li>
    <li class="animate-repeat" ng-if="getFriends().length === 0">
      <strong>No results found...</strong>
    </li>
</ul>

Now in my controller I'd implement the function as following-

$scope.$watch('q', function () {    
  $scope.getFriends = function(){
    var friends = $scope.friends;

    var params;

    if( $scope.q.indexOf(' ') > -1 ){
      var q = $scope.q.split(" ");
      params = {
        name: q[0],
        lastName: q[1]
      };
    }
    else{
      params = $scope.q;
    }

    // You can modify params for even more powerful filter... if you need actually...

    return $filter("filter")(friends, params);
  }
}

I use this approach so that I've full access to the filter right in my controller. Most of the cases I need this type of customised filter not more than once, so I'd rather put them in my controller.

One tiny glitch though, you need to define $scope.q somewhere in the controller, otherwise it'd through a Reference Error

https://plnkr.co/edit/7FTgkXOtldihFBy7cuSP?p=preview

UPDATE

@FrederikPrijck guided me through a great example about how to eliminate calling this function in every digest cycle. I've updated my answer reflecting that. Another thing is I use this approach when I need very extensive control to my filter like you don't have room for multiple input field but you need to filter by multiple properties, or sometimes I needed to update the list based on $broadcast. If you need to use a simple filter like this question, please use the accepted answer.

Upvotes: -1

Ashish Yadav
Ashish Yadav

Reputation: 95

        **Hey i have changed json object of $scope.friends**
     I have added one more key **fullName** now it will search on fullName

            angular.forEach($scope.friends,function(value,key)
           {
             value['fullName'] = value.name +" " + value.lastName;
            })

Upvotes: -1

Related Questions