Can Backbone display a collection in reverse order?

I use a Signalr hub to subscribe to events on the server. What event is sent to the hub, its successful addition of an object to the Marionette CollectionView. This, in turn, is displayed in the table.

Since the event table is essentially a blotter, I need events in the reverse order, and preferably only n-number of events.

Can "Backbone" automatically "redisplay a collection in reverse order?"

+7
source share
8 answers

To perform the collection in the reverse order, I usually use this construct:

_.each(collection.last(collection.length).reverse(), function(model){ }); 
+11
source

This section has a topic at https://github.com/marionettejs/backbone.marionette/issues/78

Although Backbone saves the collection sorted after the comparator is defined, as @breischl pointed out, Marionette does not automatically update the CollectionView when the order changes. In fact, Marionette listens for the add event in the collection and adds a new ItemView.

If you want your CollectionView always display items in reverse chronological order, and you want to add new items instead of adding, then override the appendHtml method in CollectionView as follows:

 var MyCollectionView = Backbone.Marionette.CollectionView.extend({ appendHtml: function(collectionView, itemView){ collectionView.$el.prepend(itemView.el); } }); 

If you want to be able to embed in a specific place as @dira mentioned in the comment, there is a solution posted from the link above on github by sberryman, which I reproduce here for convenience (disclaimer: I have not tested the code below):

Change appendHtml to:

 appendHtml: function(collectionView, itemView) { var itemIndex; itemIndex = collectionView.collection.indexOf(itemView.model); return collectionView.$el.insertAt(itemIndex, itemView.$el); } 

And add the following to extend jQuery to provide the insertAt function:

 (function($) { return jQuery.fn.insertAt = function(index, element) { var lastIndex; if (index <= 0) return this.prepend(element); lastIndex = this.children().size(); if (index >= lastIndex) return this.append(element); return $(this.children()[index - 1]).after(element); }; })(jQuery); 
+8
source

You will usually have a rendering in your Backbone.View subclass. So you have something like:

 render: function() { this.collection.each( function(model) { // some rendering of each element }, this ); } 

this.collection apparently a subclass of Backbone.Collection , so you can just use the underscore.js methods to get it you will like:

 this.collection.reverse().each( ... ) this.collection.sort( function(m) { ... } ).each( ... ) 

Etc.

Of course, you get one item from your backend, and you want to paste it in the right place without having to re-render all of this! Therefore, in this case, just go to the old school and insert your sort key as the rel attribute or data attribute for the elements and use this for insertAfter or similar with jQuery in your renderNewItem (or similar) method.

+1
source

The trunk automatically saves collections in sorted order. If you want to use the default sort, define the comparator() function in your collection and it will use it instead. The comparator can accept one or two arguments, more in the documentation for the basic equipment .

You can then make your collection in a .each () loop, and it will exit in the correct order. However, adding new elements to the view in sorted order is up to you.

+1
source

From what you are describing, you do not need to re-display the collection in reverse order. Just add the add event to your collection in this view and call the function that displays the newly added item and adds it to the table.

 this.collection.on('add', this.addItem); 
+1
source

You can cancel your models in such a collection ...

 this.collection.models = this.collection.models.reverse() 
0
source

If you use lodash instead of underscore, you can also do this:

 _(view.collection.models).reverse(); 
0
source

Since BackBone does not support reverse iteration of the collection (and it’s just a waste of resources to reverse or worse sort the collection), the easiest and fastest approach is to use a for loop with a reduced index compared to models in the collection.

 for (var i = collection.length - 1; i >= 0; i--) { var model = collection.models[i]; // your logic } 

It's not as elegant as sorting or reversing a collection using Underscore, but the execution is much better. Try comparing the various loops here to find out what it's worth writing foreach instead of classic for.

0
source

All Articles