Fetch models in backbone collection creation - backbone.js

I have a model and collection, when I create my collection I would like to fetch three models instead of all collections.
If I use collection.fetch() - if will fetch all objects, right now - I am fetching each model and then creating the collection, like this -
var model = new App.Model({ Id: 1 });
model.fetch().success(function() {
var collection = new Collection(model);
});
(This is a simplistic version for one model, if I want to fetch multiple, I use $.when)
There is an official/better way for doing this? or I am at the good path?

I think you can get the models that you want from the original collection and put them in a temp collection. So you can fetch the temp collection once instead fetch each model one by one.

After a little bit of thinking, I saw that my collections have many to one relation to my model.
So I used backbone-relational to fetch all of this collections.

Related

Sorting and Filtering a collection in a Paged ListBox

I have a database with 10,000 items, to which you can add and remove while the app is running.
I have a ListBox that displays at most 100 items, and supports paging.
You can filter and sort on the 10,000 items, which needs to be immediately reflected in the listbox.
I have a button that randomly selects an item as long as it passes the filters.
What is the best set of collections/views to use for this kind of operation?
So far, my first step will be to create an ObservableCollection of ALL items in the database which we will call MainOC.
Then create a List of all items that match the filter by parsing MainOC which we will call FilteredList.
Then create a ListCollectionView based on the above List that holds the first 100 items.
CONS:
You have to recreate the ListCollectionView every time a sort operation is applied.
You have to recreate the ListCollectionView every time you page.
You have to recreate the ListCollectionView every time a filter is changed.
You have to recreate the ListCollectionView every time an item is added or removed to MainOC.
Is there a better approach that I am missing?
For example, I see that you can apply filters to a ListCollectionView. Should I populate my ListCollectionView with all 10,000 items? But then how can I limit how many items my ListBox is displaying?
Should I be doing my filtering and sorting directly against the database? I could build FilteredList directly off the database and create my ListCollectionView based off that, but this still has all the cons listed above.
Looking for any input you can provide!
This is a problem which is easily solved using DynamicData . Dynamic data is based on rx so if you are not familiar with the wonderful Rx I suggest you start learning it. There is quite a bit of a learning curve but but the rewards are huge.
Anyway back to my answer, the starting point of dynamic data is to get some data into a cache which is constructed with a key as follows
var myCache = new SourceCache<MyObject, MyId>(myobject=>myobject.Id)
Obviously being a cache there are methods to add, update and remove so I will not show those here.
Dynamic data provides a load of extensions and some controllers to dynamically interrogate the data. For paging we need a few elements to solve this problem
//this is an extension of observable collection optimised for dynamic data
var collection = new ObservableCollectionExtended<MyObject>();
//these controllers enable dynamically changing filter, sort and page
var pageController = new PageController();
var filterController = new FilterController<T>();
var sortController = new SortController<T>();
Create a stream of data using these controllers and bind the result to the collection like this.
var mySubscription = myCache.Connect()
.Filter(filterController)
.Sort(sortController)
.Page(pageController)
.ObserveOnDispatcher() //ensure we are on the UI thread
.Bind(collection)
.Subscribe() //nothing happens until we subscribe.
At any time you can change the parameters of the controllers to filter, sort, page and bind the data like follows
//to change page
pageController.Change(new PageRequest(1,100));
//to change filter
filterController.Change(myobject=> //return a predicate);
//to change sort
sortController .Change( //return an IComparable<>);
And as if by magic the observable collection will self-maintain when any of the controller parameters change or when any of the data changes.
The only thing you now have to consider is the code you need for loading the database data into the cache.
In the near future I will create a working example of this functionality.
For more info on dynamic data see
Dynamic data on Github
Wpf demo app

Adding one model to multiple collections

My application has two collection instances, allItems and someItems.
I have populated allItems, and then have added the first model of allItems to someItems, like this:
someItems.add(allItems.get(0).toJSON());
The problem is this creates a duplicate. If I change an attribute of that model in someItems, allItems will not be affected.
How can I effectively link the two?
You should be able to do
someItems.add(allItems.get(0));
to add the model and keep them in sync.
allItems.get(0).toJSON() will create a JSON object which is different from allItems.get(0).
That's why you can't maintain only one object.
Delete .toJSON() and have a try.

Are collections required?

Sorry this is a noob question but if I only need some initial data when the application first loads is a collection always needed or can the model fetch the data and pass it directly to the view?
Nothing in backbone is really "required". It's a very thin, more-than-one-way-to-do-it framework. Jeremy recommends data that can be bootstrapped in the initial page load be handled that way, so your HTML could include you initial data as JSON in a <script> tag. You can pass that JSON to a Backbone.Collection (if it's a list of similar records) or a new Backbone.Model (if it's a single domain object). You can also just use a model and call model.fetch to get your initial data. Model vs. Collection is more about single domain object with name/value pairs vs list of many objects where iterating, sorting, filtering are common.

Filtering a collection vs. several collections in Backbone?

When is it appropriate to filter a collection vs. having several collections in Backbone?
For example, consider a music library app. It would have a view for displaying genres and another view for displaying the selected genre's music.
Would you rather make one huge collection with all the music and then filter it or several smaller ones?
Having just one collection would allow you add features for filtering by other attributes as well, but suppose you have tons of music: how do you prevent loading it all in when the application starts if the user if only going to need 1 genre?
I think the simplest approach is having a common unique Collection that, intelligently, fetch an already filtered by genre data from the server:
// code simplified and no tested
var SongsCollection = Backbone.Collection.extend({
model: Song,
url: function() {
return '/songs/' + this.genre;
},
initialize: function( opts ){
this.genre = opts.genre;
}
});
var mySongsCollection = new SongsCollection({ genre: "rock" });
mySongsCollection.fetch();
You have to make this Collection to re-fetch data from the server any time the User changes the selected genre:
mySongsCollection.genre = "punk";
mySongsCollection.fetch();
It's mostly a design choice, but my vote would be to choose a scheme that loosely reflects the database storing the collections.
If you're likely to be storing data in an SQL database, you will more likely than not have separate tables for songs and genres. You would probably connect them either via a genre_id column in the song table, or (if songs can have more than one genre) in terms of a separate song_genres join table. Consequently, you would probably want separate collections representing genres and the songs within them. In this case, backbone-relational might be very useful tool for helping keep them straight.
If you're storing information in any kind of relational/key-value/document store, it might make sense to simply store the genre with the song directly and filter accordingly. In this case, you might end up storing your document keys/queries in such a way that you could access songs either directly (e.g., via songs) or through the genre (e.g., genre:genre_id/songs). If this is the route you go, it may be more convenient to simply create a single huge collection of songs and plan to set up corresponding filters in both the application and database environment.

Backbone.js: How to get the index of a model in a Backbone Collection?

Is there a way to find the index of a model within a collection?
Let's say in a view we have a model we're working on, could that model spit out it's index within the collection it's currently inside of? I'd like to do this because I want to access the model above or below the current target.
In other words is there something like:
index = this.model.index
modelAbove = this.collection.at( index-1 )
My data is a nested set so I can just do a search on the "lft" or "rgt" columns, but I didn't want to reinvent the wheel if Backbone already has this info available.
yes, backbone provides access to many underscore.js methods on models and collections, including an indexOf method on collections. it also provides an at method like you've shown.
var index = this.collection.indexOf(this.model);
var modelAbove = this.collection.at(index-1);

Resources