1

My custom filter should output:

Mark

...however it's outputting:

  • M
  • a
  • r
  • k

Here's my view:

  <body ng-controller="MainCtrl">
    <ul>
      <li ng-repeat="friend in friends | myFriend:currentUser">
        {{ friend }}
      </li>
    </ul>
  </body>

...and controller:

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

app.filter('myFriend', function () {
  return function (items, currentUser) {
    console.log(items);
    console.log(currentUser);
    for (var i = 0; i < items.length; i++) {
      if (items[i] === currentUser) {
        return items[i];
      }
    }

  };
});

app.controller('MainCtrl', function($scope) {
  $scope.currentUser = 'Mark';
  $scope.friends = ['Andrew', 'Will', 'Mark', 'Alice', 'Todd'];
});

Here is my Plunker: http://plnkr.co/edit/JCKAt05MPlrvIZBCGO0n?p=preview

How can my custom filter output "Mark"?

4 Answers 4

2

That is because you are passing a string from the filter instead of array of string. ng-repeat will iterate though the characters (string is an array of chars) of the string Mark and display it. You need to instead pass array to ng-repeat. Filter is run first before applying source to ng-repeat. Example:

for (var i = 0; i < items.length; i++) {
  if (items[i] === currentUser) {
    return [items[i]];
  }
}

In your specific case you could just as well do as below, without creating any custom filter:

 <li ng-repeat="friend in friends | filter:currentUser:true">
  {{ friend }}
</li>
Sign up to request clarification or add additional context in comments.

Comments

1

As I presume you are aware the filter is being applied to the list friends.

Your filter is returning a single string value.

Your ng-repeat can be thought of as:

ng-repeat="friend in (friends | myFriend:currentUser)"

which means you are trying to loop over the string returned by your myFriend filter. For the browser you're using ng-repeat over a string loops over each character in the string.

(Note: this might not happen on every browser, because some browsers (e.g. IE7) do not allow [] subscripting on strings. (Underneath it all, ng-repeat would rely on the value having a length property and [] subscripting.)

The following may produce the result you want (assuming you only ever want one name to be shown from the list)

  <body ng-controller="MainCtrl">
    <ul>
      <li>
        {{ friends | myFriend:currentUser }}
      </li>
    </ul>
  </body>

Comments

1

My strong suggestion is dont write extra code. Its like reinventing the wheel. Instead stick to the general procedure and filter it out. A small change in your friends array will get you better result with minimal coding. Use angular to minimalize your coding.

    <!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <script data-require="[email protected]" src="https://code.angularjs.org/1.4.2/angular.js" data-semver="1.4.2"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <ul>
      <li ng-repeat="friend in friends | filter:{name:currentUser}">
        {{ friend.name }}
      </li>
    </ul>
  </body>

</html>

app.js

app.controller('MainCtrl', function($scope) {
  $scope.currentUser = 'Mark';
  $scope.friends = [{'name':'Andrew'}, {'name':'Will'}, {'name':'Mark'}, {'name':'Alice'}, {'name':'Todd'}];
});

Comments

0

Try below updated filter. You are returning String whereas you should return an array. Thats why ng-repeat is considering that String as an array and iterating every letters.

app.filter('myFriend', function () {
    return function (items, currentUser) {
        console.log(items);
        console.log(currentUser);
        var finalItems = [];
        for (var i = 0; i < items.length; i++) {
            if (items[i] === currentUser) {
                finalItems.push(items[i]);
            }
        }
        return finalItems;
    };
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.