Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ember pagination full example

Tags:

ember.js

I was wondering if there is a complete example that could demonstrate how can we use pagination with ember.js

I have a table that has many rows, so i want to use pagination to help the user with the data analysis.

I've already see the Ember.PaginationSupport.js but i can't find a way to work with this in a html view.

like image 591
Juan Jardim Avatar asked Oct 22 '12 09:10

Juan Jardim


3 Answers

The updated example below works with ember.js RC1 -- 03/14/2013

First you need to add a pagination like mixin as one doesn't yet exist in the ember core

var get = Ember.get, set = Ember.set;

Ember.PaginationMixin = Ember.Mixin.create({

  pages: function() {

    var availablePages = this.get('availablePages'),
    pages = [],
    page;

    for (i = 0; i < availablePages; i++) {
      page = i + 1;
      pages.push({ page_id: page.toString() });
    }

    return pages;

  }.property('availablePages'),

  currentPage: function() {

    return parseInt(this.get('selectedPage'), 10) || 1;

  }.property('selectedPage'),

  nextPage: function() {

    var nextPage = this.get('currentPage') + 1;
    var availablePages = this.get('availablePages');

    if (nextPage <= availablePages) {
        return Ember.Object.create({id: nextPage});
    }else{
        return Ember.Object.create({id: this.get('currentPage')});
    }

  }.property('currentPage', 'availablePages'),

  prevPage: function() {

    var prevPage = this.get('currentPage') - 1;

    if (prevPage > 0) {
        return Ember.Object.create({id: prevPage});
    }else{
        return Ember.Object.create({id: this.get('currentPage')});
    }

  }.property('currentPage'),

  availablePages: function() {

    return Math.ceil((this.get('content.length') / this.get('itemsPerPage')) || 1);

  }.property('content.length'),

  paginatedContent: function() {

    var selectedPage = this.get('selectedPage') || 1;
    var upperBound = (selectedPage * this.get('itemsPerPage'));
    var lowerBound = (selectedPage * this.get('itemsPerPage')) - this.get('itemsPerPage');
    var models = this.get('content');

    return models.slice(lowerBound, upperBound);

  }.property('selectedPage', 'content.@each')

});

Next you need to use the mixin above in your ArrayController like so

PersonApp.PersonController = Ember.ArrayController.extend(Ember.PaginationMixin, {  
    itemsPerPage: 2
});

Next you can add a simple helper view to display the page numbers as li tags

PersonApp.PaginationView = Ember.View.extend({
    templateName: 'pagination',
    tagName: 'li',

    page: function() {
        return Ember.Object.create({id: this.get('content.page_id')});
    }.property()
});

Your routes might look something like this (nested page under the parent)

PersonApp.Router.map(function(match) {
    this.resource("person", { path: "/" }, function() {
        this.route("page", { path: "/page/:page_id" });
    });
});

PersonApp.PersonPageRoute = Ember.Route.extend({
    model: function(params) {
        return Ember.Object.create({id: params.page_id});
    },
    setupController: function(controller, model) {
        this.controllerFor('person').set('selectedPage', model.get('id'));
    }
});

PersonApp.PersonRoute = Ember.Route.extend({
    model: function(params) {
        this.controllerFor('person').set('selectedPage', 1);
        return PersonApp.Person.find();
    }
});

And finally, you need to add some html to display it

<script type="text/x-handlebars" data-template-name="application">

  <div id="main">
    {{ outlet }}
  </div>

</script>

<script type="text/x-handlebars" data-template-name="person">

<table width="250px">                                                               
<thead>
<th>id</th>
<th>username</th>
</thead>
<tbody>
   {{#each person in controller.paginatedContent}}
    <tr>
      <td>{{person.id}}</td>
      <td>{{view Ember.TextField valueBinding="person.username"}}</td>
    </tr>
   {{/each}}
</tbody>
</table>

<div name="prev">{{#linkTo 'person.page' prevPage target="controller"}}Prev{{/linkTo}}</div>
<ul class="pagination gui-text">
  {{#each pages}}
    {{view PersonApp.PaginationView contentBinding="this"}}
  {{/each}}
</ul>
<div name="next">{{#linkTo 'person.page' nextPage target="controller"}}Next{{/linkTo}}</div>

</script>

<script type="text/x-handlebars" data-template-name="pagination">

{{#with view}}
{{#linkTo 'person.page' page}}
  {{content.page_id}}
{{/linkTo}}                                                                         
{{/with}}

</script>

Here is a full working project with this in action if you want to see it work

https://github.com/toranb/ember-pagination-example

like image 198
Toran Billups Avatar answered Oct 31 '22 19:10

Toran Billups


After some improvements and help of my friend edgar we came up with a very simple solution that you could check out in GitHub

basically we extended Ember.ArrayProxy in order to accomplish the pagination and also added actions to manage the previus and next pages.

Thanks to @Toran Billups for his solution and algo @Jeremy Brown

like image 40
Juan Jardim Avatar answered Oct 31 '22 19:10

Juan Jardim


I have had great success with https://github.com/notmessenger/emberjs-pageable but Ember now has something built in natively into ArrayController called arrangedContent that does this. You can also specify default sort orders on specific fields on your models. Ember.js and arrangedContent talks about it a little bit.

like image 1
Jeremy Brown Avatar answered Oct 31 '22 20:10

Jeremy Brown