I. Avant-propos

AngularJS est doté d'un système de filtrage et de tri riche basé sur des prédicats. Le filtre orderByorderBy peut être utilisé avec la directive ng-repeat :

 
Sélectionnez
<ul>
  <li ng-repeat="item in stories | orderBy:predicate:date"><a href=""></a></li>
</ul>

Aujourd'hui, nous allons utiliser orderBy à l'intérieur d'un contrôleur utilisant l'injection de dépendances pour organiser de multiples flux en un torrent de news triées par date.

II. L'itération dans les contrôleurs

Avant de trier et d'afficher des éléments (des stories dans l'exemple), nous avons besoin de les récupérer dans une structure de données adaptée. Un tableau suffira (app/scripts/controllers/main.js) :

 
Sélectionnez
$scope.stories = [];

Ensuite, nous devons concaténer des éléments à cette collection, mais seulement s'ils n'ont pas déjà été ajoutés. Pour ce faire, nous allons utiliser une fonction pour séparer cela de la récupération des éléments :

 
Sélectionnez
$scope.fetchFeed = function(feed) {
  feed.items = [];

  var apiUrl = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D'";
  apiUrl += encodeURIComponent(feed.url);
  apiUrl += "'%20and%20itemPath%3D'feed.entry'&format=json&diagnostics=true&callback=JSON_CALLBACK";

  $http.jsonp(apiUrl).
    success(function(data) {
      if (data.query.results) {
        feed.items = data.query.results.entry;
      }
      addStories(feed.items);

La fonction addStories a juste besoin de parcourir chaque élément du flux pour déterminer s'il a déjà été ajouté à $scope.stories. L'API angular.forEachangular.forEach du module ng est parfaite pour ça :

 
Sélectionnez
function addStories(stories) {
  var changed = false;
  angular.forEach(stories, function(story, key) {
    if (!storyInCollection(story)) {
      $scope.stories.push(story);
      changed = true;
    }
  });
}

Comme vous pouvez le voir, forEach accepte un tableau et une fonction pour récupérer chaque élément. La fonction storyInCollection doit maintenant parcourir chaque élément existant pour vérifier qu'il a déjà été ajouté. Déterminer quel élément est unique est facile puisque les flux ont un id :

 
Sélectionnez
function storyInCollection(story) {
  for (var i = 0; i < $scope.stories.length; i++) {
    if ($scope.stories[i].id === story.id) {
      return true;
    }
  }
  return false;
}

III. Stockage des données

Maintenant que nous avons récupéré une liste d'éléments, il faut les trier par date, comme dans un vrai lecteur de flux. À chaque fois que addStories change la liste d'éléments, il faut la trier. AngularJS n'a pas vraiment de méthodes du style map ou some qu'on peut trouver dans ECMAScript 5, mais il fournit une API permettant d'accéder aux modules de filtrage et de tri typiquement utilisés dans les templates.

Pour accéder à cette fonctionnalité, il faut charger $filter :

 
Sélectionnez
angular.module('djsreaderApp')
  .controller('MainCtrl', function($scope, $http, $timeout, $filter) {

$filter va retourner une fonction sachant trier ou filtrer des tableaux. Ça veut dire qu'il faut l'appeler avec le nom de la méthode souhaitée et appeler la valeur retournée avec un tableau et une expression : $filter(filter)(array, expression). Pour ajouter un tri à nos flux, nous appelons $filter()() et nous mettons à jour le tableau $scope.stories :

 
Sélectionnez
// A la fin de addStories
if (changed) {
  $scope.stories = $filter('orderBy')($scope.stories, 'date');
}

La dernière chose à faire consiste à mettre à jour le template dans le fichier app/views/mail.html :

 
Sélectionnez
<ul>
  <li ng-repeat="item in stories"><a href=""></a></li>
</ul>

Si vous ajoutez plusieurs flux en utilisant l'interface Web, nous devrions les voir combinés en un torrent de news.

IV. Conclusion

Image non disponible

La version pour ce tutoriel est la ff4d6a6.

V. Remerciements

L'article original peut être lu sur le site DailyJSDailyJS : AngularJS: Iterators and FiltersAngularJS: Iterators and Filters.

Je remercie également f-leb pour sa relecture attentive et assidue.