web-dev-qa-db-fra.com

défilement infini avec ember.js (chargement paresseux)

J'ai une vue où il peut y avoir un grand nombre d'éléments à parcourir par l'utilisateur et j'aimerais implémenter un défilement infini pour permettre le chargement progressif du contenu.

Il semble que certaines personnes ont fait la pagination mais Google n'indique personne qui discute de la façon dont ils ont fait des listes infinies avec Ember/Ember Data. Quelqu'un a déjà travaillé sur ce sujet et a un article de blog/un exemple de code à partager?

54
outside2344

Étiez-vous au courant du nouveau composant Ember.ListView?

https://github.com/emberjs/list-view

Il a été annoncé lors du Meetup février = San Francisco Ember. Voici un diaporama d'Erik Bryn, l'un des développeurs de Ember Core à propos de son utilisation:

http://talks.erikbryn.com/ember-list-view/

15
commadelimited

J'ai implémenté un mécanisme de défilement infini au GitHub Dashboardprojet , je développe actuellement. La fonctionnalité est ajoutée dans commit 68d1728 .

L'idée de base est d'avoir un LoadMoreView qui invoque la méthode loadMore sur le contrôleur chaque fois que la vue est visible dans la fenêtre courante. J'utilise le plugin jQuery inview pour cela. Il vous permet de vous inscrire à un événement inview, qui est déclenché lorsque l'élément du sélecteur spécifié est visible à l'écran et lorsqu'il disparaît.

Le contrôleur possède également des propriétés qui indiquent s'il y a plus d'éléments à charger et s'il y a actuellement des éléments récupérés. Ces propriétés sont appelées canLoadMore et isLoading.

Le LoadMoreView ressemble essentiellement à ceci:

App.LoadMoreView = Ember.View.extend({
  templateName: 'loadMore',
  didInsertElement: function() {
    var view = this;
    this.$().bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
      if (isInView) Ember.tryInvoke(view.get('controller'), 'loadMore');
    });
  }
});

où le modèle loadMore est défini comme suit:

{{#if isLoading}}
    fetching some more stuff <img width="10" src="img/ajax-loader.gif" >
{{else}}
    {{#if canLoadMore}}
        <a {{action "loadMore" target="controller" }}>click to load more items</a>
    {{else}}
        <i>no more items</i>
    {{/if}}
{{/if}}

Le contrôleur qui gère la récupération de plusieurs éléments est ensuite implémenté comme suit. Notez que dans la méthode loadMore, une requête sur le magasin est exécutée, ce qui charge une page spécifique d'entrées pour un modèle.

App.EventsController = Ember.ArrayController.extend({
  currentPage: 1,

  canLoadMore: function() {
    // can we load more entries? In this example only 10 pages are possible to fetch ...
    return this.get('currentPage') < 10;
  }.property('currentPage'),

  loadMore: function() {
    if (this.get('canLoadMore')) {
      this.set('isLoading', true);
      var page = this.incrementProperty('currentPage');

      // findQuery triggers somehing like /events?page=6 and this
      // will load more models of type App.Event into the store
      this.get('store').findQuery(App.Event, { page: page });
    } else {
      this.set('isLoading', false);
    }
  }
});

Il ne reste plus qu'à définir initialement le content du contrôleur sur le résultat d'une fonction filter, donc le content est mis à jour lorsque de nouveaux modèles sont chargés dans le magasin ( ce qui se produit en raison de la méthode findQuery dans le loadMore du contrôleur). En outre, un hachage query est ajouté lorsque le filter est appelé. Cela garantit qu'une requête initiale au serveur est effectuée.

App.eventsController = App.EventsController.create({
    content: []
});

var events = App.store.filter(App.Event, { page: 1 }, function(data) {
    // show all events; return false if a specific model - for example a specific
    // type of event - shall not be included
    return true;
});
61
pangratz

J'écris un plugin de pagination infini pour Ember basé sur le travail de @ pangratz.

Veuillez déclencher tout problème si vous avez des questions ou des améliorations que vous souhaitez.

5
iHiD

Je recommanderais d'utiliser Ember Infinity addon. Il prend en charge Ember 1.10 à 2.0 +. Il est relativement facile à configurer. Il vous suffit de modifier votre itinéraire et modèle.

Route (Product est un exemple de modèle):

import InfinityRoute from 'ember-infinity/mixins/route';

export default Ember.Route.extend(InfinityRoute, {
  model() {
    /* Load pages of the Product Model, starting from page 1, in groups of 12. */
    return this.infinityModel('product', { perPage: 12, startingPage: 1 });
  }
});

Modèle:

{{#each model as |product|}}
  ...
{{/each}}

{{infinity-loader infinityModel=model}}

Quand {{infinity-loader}} le composant devient visible, il envoie une action à votre itinéraire, il sait donc mettre à jour le tableau de modèles avec de nouveaux enregistrements (récupérés).

La première demande sera envoyée à:

/products?per_page=12&page=1

Vous devez donc également préparer votre API backend pour gérer ces paramètres de requête. Il est évidemment personnalisable, jetez un œil à section Utilisation avancée du fichier Lisez-moi .

Remarque :

L'utilisation de ListView (réponse de @ commadelimited) et des vues avec ArrayController (réponse de @ pangratz) est obsolète/supprimée à partir de Ember 2.0 étant une version stable.

1
Daniel Kmak