Пользовательский фильтр AngularJS с аргументом

Мой пользовательский фильтр должен выводить:

Отметка

... однако он выводит:

  • M
  • a
  • r
  • k

Вот мой взгляд:

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

...и контроллер:

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'];
});

Вот мой плункер: http://plnkr.co/edit/JCKAt05MPlrvIZBCGO0n?p=preview

Как мой пользовательский фильтр может выводить «Отметить»?


person Ryan    schedule 07.07.2015    source источник


Ответы (4)


Как я полагаю, вы знаете, что фильтр применяется к списку друзей.

Ваш фильтр возвращает одно строковое значение.

Ваш ng-repeat можно рассматривать как:

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

что означает, что вы пытаетесь перебрать строку, возвращаемую вашим фильтром myFriend. Для браузера вы используете ng-repeat для строковых циклов для каждого символа в строке.

(Примечание: это может происходить не во всех браузерах, поскольку некоторые браузеры (например, IE7) не разрешают [] подписку на строки. (Под всем этим ng-repeat будет полагаться на значение, имеющее свойство длины и [] подписку.)

Следующее может привести к желаемому результату (при условии, что вы хотите, чтобы из списка отображалось только одно имя)

  <body ng-controller="MainCtrl">
    <ul>
      <li>
        {{ friends | myFriend:currentUser }}
      </li>
    </ul>
  </body>
person Nicholas Daley-Okoye    schedule 07.07.2015

Это потому, что вы передаете строку из фильтра вместо массива строк. ng-repeat будет перебирать символы (строка представляет собой массив символов) строки Mark и отображать ее. Вместо этого вам нужно передать массив в ng-repeat. Фильтр запускается перед применением источника к ng-repeat. Пример:

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

В вашем конкретном случае вы можете сделать так же, как показано ниже, без создания какого-либо настраиваемого фильтра:

 <li ng-repeat="friend in friends | filter:currentUser:true">
  {{ friend }}
</li>
person PSL    schedule 07.07.2015

Мое настоятельное предложение - не писать лишний код. Это как изобретать велосипед. Вместо этого придерживайтесь общей процедуры и отфильтруйте ее. Небольшое изменение в вашем массиве друзей даст вам лучший результат с минимальным кодированием. Используйте angular, чтобы минимизировать кодирование.

    <!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'}];
});
person Alaksandar Jesus Gene    schedule 07.07.2015

Попробуйте ниже обновленный фильтр. Вы возвращаете строку, тогда как вы должны вернуть массив. Вот почему ng-repeat рассматривает эту строку как массив и повторяет каждую букву.

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;
    };
});
person Nitesh Mishra    schedule 07.07.2015