In the below example, when using {{#each items}} instead of {{#items}}, the dom will render with the results spliced in place instead of completely replacing. With 20 items initially showing, and 5 items return, the first 5 will be updated, with the other 15 still existing.
- define(['jquery', 'models/alerts', 'components/paginate', 'models/posts', 'can'], function( $, Alerts, Paginate, posts ) {
- var Query = can.Component.extend({
- tag: 'listing',
- scope: function( attr ) {
- if(typeof attr.filters != 'object') {
- attr.filters = {};
- }
- return {
- loading: true,
- paginate: new Paginate({
- limit: 20
- }),
- filters: new can.Map(attr.filters),
- items: new can.List([]),
- query: can.compute(function() {
- var self = this;
- var params = {
- limit: this.attr('paginate.limit'),
- offset: this.attr('paginate.offset'),
- filters: this.attr('filters').attr()
- };
- var queryDeferred = Posts.findAll(params);
- queryDeferred.then(function( items ) {
- self.attr('paginate.count', items.length );
- });
- return queryDeferred;
- })
- };
- },
- events: {
- init: function() {
- this.update();
- },
- update: function() {
- var query = this.scope.attr('query'),
- scope = this.scope;
- if(can.isDeferred(query)) {
- query.then(function( items ) {
- scope.attr('items').replace(items);
- });
- query.fail(Alerts.failure);
- } else {
- this.scope.attr('items').replace(query.attr(), true);
- }
- },
- '{query} change': 'update',
- '{items} change': function( list, ev, index, mode, newItems, oldItem ) {
- this.scope.attr('loading', false);
- },
- 'form.query submit': function( el, ev ) {
- ev.preventDefault();
- can.batch.start();
- this.scope.attr('filters', can.deparam(el.serialize()));
- this.scope.attr('paginate.offset', 0);
- can.batch.stop();
- }
- }
- });
- return Query;
- });
- define(['jquery', 'can'], function( $ ) {
- var Paginate = can.Map.extend({
- offset: 0,
- count: 0,
- limit: 5,
- next: function () {
- this.attr('offset', this.offset + this.limit);
- },
- prev: function () {
- this.attr('offset', this.offset - this.limit);
- },
- canNext: function () {
- return this.attr('count') == this.attr('limit');
- },
- canPrev: function () {
- return this.attr('offset') > 0;
- },
- page: function (newVal) {
- if (newVal === undefined) {
- return Math.floor(this.attr('offset') / this.attr('limit')) + 1;
- } else {
- this.attr('offset', (parseInt(newVal, 10) - 1) * this.attr('limit'));
- }
- }
- });
- return Paginate;
- });