Skip to content

Commit

Permalink
Merge pull request #9 from CargoSense/find-options
Browse files Browse the repository at this point in the history
Support additional parameters for infinityModel() closes #11
  • Loading branch information
hhff committed Apr 8, 2015
2 parents 0001d4d + c4528cd commit 567bb06
Show file tree
Hide file tree
Showing 9 changed files with 305 additions and 44 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ When the new records are loaded, they will automatically be pushed into the Mode

## Advanced Usage

### infinityModel

You can also provide additional parameters to `infinityModel` that
will be passed to your backend server in addition to the
pagination params. For instance, in the following example a `category`
parameter is added:

```js
return this.infinityModel("product", { perPage: 12, startingPage: 1,
category: "furniture" });
```

### infinity-loader

The `infinity-loader` component as some extra options to make working with it easy!

* **destroyOnInfinity**
Expand Down
100 changes: 59 additions & 41 deletions addon/mixins/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ export default Ember.Mixin.create({
*/
_currentPage: 0,

/**
@private
@property _extraParams
@type Object
@default {}
*/
_extraParams: {},

/**
@private
@property _loadingMore
Expand Down Expand Up @@ -84,13 +92,18 @@ export default Ember.Mixin.create({

this.set('_infinityModelName', modelName);

options = options || {};
options = options ? Ember.merge({}, options) : {};
var startingPage = options.startingPage || 1;
var perPage = options.perPage || this.get('_perPage');

delete options.startingPage;
delete options.perPage;

this.set('_perPage', perPage);
this.set('_extraParams', options);

var promise = this.store.find(modelName, { page: startingPage, per_page: perPage });
var params = Ember.merge({ page: startingPage, per_page: perPage }, options);
var promise = this.store.find(modelName, params);

promise.then(
function(infinityModel) {
Expand All @@ -108,48 +121,53 @@ export default Ember.Mixin.create({
return promise;
},

actions: {
/**
Trigger a load of the next page of results.
@method infinityLoad
@return {Boolean}
*/
infinityLoad: function() {
var _this = this;
var nextPage = this.get('_currentPage') + 1;
var perPage = this.get('_perPage');
var totalPages = this.get('_totalPages');
var model = this.get('controller.model');
var modelName = this.get('_infinityModelName');

if (!this.get('_loadingMore') && this.get('_canLoadMore')) {
this.set('_loadingMore', true);

var promise = this.store.find(modelName, { page: nextPage, per_page: perPage });
promise.then(
function(infinityModel) {
model.pushObjects(infinityModel.get('content'));
_this.set('_loadingMore', false);
_this.set('_currentPage', nextPage);
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelUpdated', { lastPageLoaded: nextPage, totalPages: totalPages, newObjects: infinityModel });
if (!_this.get('_canLoadMore')) {
_this.set('controller.model.reachedInfinity', true);
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelLoaded', { totalPages: totalPages });
}
},
function() {
_this.set('_loadingMore', false);
throw new Ember.Error("You must pass a Model Name to infinityModel");
/**
Trigger a load of the next page of results.
@method infinityLoad
@return {Boolean}
*/
_infinityLoad: function() {
var _this = this;
var nextPage = this.get('_currentPage') + 1;
var perPage = this.get('_perPage');
var totalPages = this.get('_totalPages');
var model = this.get('controller.model');
var modelName = this.get('_infinityModelName');

if (!this.get('_loadingMore') && this.get('_canLoadMore')) {
this.set('_loadingMore', true);

var params = Ember.merge({ page: nextPage, per_page: perPage }, this.get('_extraParams'));
var promise = this.store.find(modelName, params);
promise.then(
function(infinityModel) {
model.pushObjects(infinityModel.get('content'));
_this.set('_loadingMore', false);
_this.set('_currentPage', nextPage);
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelUpdated', { lastPageLoaded: nextPage, totalPages: totalPages, newObjects: infinityModel });
if (!_this.get('_canLoadMore')) {
_this.set('controller.model.reachedInfinity', true);
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelLoaded', { totalPages: totalPages });
}
);
} else {
if (!this.get('_canLoadMore')) {
this.set('controller.model.reachedInfinity', true);
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelLoaded', { totalPages: totalPages });
},
function() {
_this.set('_loadingMore', false);
throw new Ember.Error("You must pass a Model Name to infinityModel");
}
);
} else {
if (!this.get('_canLoadMore')) {
this.set('controller.model.reachedInfinity', true);
Ember.run.scheduleOnce('afterRender', _this, 'infinityModelLoaded', { totalPages: totalPages });
}
return false;
}
return false;
},

actions: {
infinityLoad: function() {
this._infinityLoad();
}
}
});
77 changes: 77 additions & 0 deletions tests/acceptance/infinity-route-with-meta-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Ember from 'ember';
import { module, test } from 'qunit';
import startApp from '../helpers/start-app';
import Pretender from 'pretender';

var App, server;

var posts = [
{ id: 1, name: "Squarepusher", category: "a" },
{ id: 2, name: "Aphex Twin", category: "b" },
{ id: 3, name: "Universal Indicator", category: "a" },
{ id: 4, name: "Mike & Rich", category: "b" },
{ id: 5, name: "Alroy Road Tracks", category: "a" },
{ id: 6, name: "AFX", category: "b" }
];

module('Acceptance: Infinity Route', {
setup: function() {
App = startApp();
server = new Pretender(function() {
this.get('/posts', function(request) {
var body, subset, perPage, startPage, offset;

if (request.queryParams.category) {
subset = posts.filter(function(post) {
return post.category === request.queryParams.category;
});
} else {
subset = posts;
}
perPage = parseInt(request.queryParams.per_page);
startPage = parseInt(request.queryParams.page);

var pageCount = Math.ceil(subset.length / perPage);
offset = perPage * (startPage - 1);
subset = subset.slice(offset, offset + perPage);

body = { posts: subset, meta: { total_pages: pageCount } };

return [200, {"Content-Type": "application/json"}, JSON.stringify(body)];
});
});
},
teardown: function() {
Ember.run(App, 'destroy');
server.shutdown();
}
});

test('it works when meta is present in payload', function(assert) {
visit('/');

andThen(function() {
var postsTitle = find('#posts-title');
var postList = find('ul');
var infinityLoader = find('.infinity-loader');

assert.equal(postsTitle.text(), "Listing Posts");
assert.equal(postList.find('li').length, 6);
assert.equal(infinityLoader.hasClass('reached-infinity'), true);
});
});

test('it works with parameters', function(assert) {
visit('/category/a?per_page=2');

andThen(function() {
var postsTitle = find('#posts-title');
var postList = find('ul');
var infinityLoader = find('.infinity-loader');

assert.equal(postsTitle.text(), "Listing Posts using Parameters");
assert.equal(postList.find('li').length, 2);
assert.equal(postList.find('li:first-child').text(), "Squarepusher");
assert.equal(infinityLoader.hasClass('reached-infinity'), false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ test('it works when meta is not present in payload', function(assert) {
assert.equal(postList.find('li').length, 2);
assert.equal(infinityLoader.hasClass('reached-infinity'), true);
});
});
});
5 changes: 3 additions & 2 deletions tests/dummy/app/models/post.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import DS from 'ember-data';

export default DS.Model.extend({
name: DS.attr('string')
});
name: DS.attr('string'),
category: DS.attr('string')
});
1 change: 1 addition & 0 deletions tests/dummy/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ var Router = Ember.Router.extend({

Router.map(function() {
this.route('home', { path: '/' });
this.route('category', { path: '/category/:category' });
});

export default Router;
9 changes: 9 additions & 0 deletions tests/dummy/app/routes/category.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Ember from 'ember';
import InfinityRoute from 'ember-infinity/mixins/route';

export default Ember.Route.extend(InfinityRoute, {
model: function(params) {
return this.infinityModel('post', { category: params.category,
perPage: 2 });
}
});
9 changes: 9 additions & 0 deletions tests/dummy/app/templates/category.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<h2 id="posts-title">Listing Posts using Parameters</h2>

<ul>
{{#each model as |item|}}
<li>{{item.name}}</li>
{{/each}}
</ul>

{{infinity-loader infinityModel=model}}
Loading

0 comments on commit 567bb06

Please sign in to comment.