To be able to know if the collection was populated, or is beeing populated, there might be something like
collection.fetch();
collection.isFetching()===true; // display loading
(collection.isFetching()===false; && collection.length) // display no records found
Real usecase (simplification, the objects are passed deep in the system):
javascript()
// somewhere in the code
collection = new MyCollection();
// somewhere else in the code
view = new MyView({collection:collection});
// and somewhere else in the code
collection.fetch();
the view listens for collection signals, and displays either loading/no records/records list
for model, there could be even save/delete/update thing
Hi @g00fy-! I would recommend that you use the "request"
and "sync"
events for this purpose. What do you think?
collection.on('request', function() {
// loading...
}).on('sync', function() {
// display records or "none found"
});
collection.fetch();
_Edit - I meant the "request"
event, not "fetch"
._
I think that's a swell idea @braddunbar!
Thanks @caseywebdev! :)
Let us know if that doesn't work for you @g00fy-.
@braddunbar , @caseywebdev the idea is to decouple those two parts. (view should be able to get collection in any state, not just _'clean'_ collection)
I am aware that I can do this using signals, but in many cases this can not be done this way. The order of actions matters
I agree that view should listen for 'request' and 'sync' signals, but the request signal might be sent before the collection is passed to the view, therefore view has no idea that the collection is fetching.
Consider an example, where your view gets an arbitrary collection. This collection can be either _fetched_ , _fetching_ or _unfetched_ when it is passed to the view (tl:dr see example 3).
collection = new Backbone.Collection();
view = new Backbone.View({collection:collection});
view.render();
// what should the view render ?
collection.fetch() // now sync signal gets sent
collection = new Backbone.Collection();
collection.fetch(); // now sync signal gets sent
// after fetch completes
// view won't be able to receive 'sync' signal
view = new Backbone.View({collection:collection});
view.render();
// at this point collection.length == 0.
// I guess the view can listen to 'sync' and then render 'empty'
collection = new Backbone.Collection();
collection.fetch(); // now 'request' signal gets sent, but it is pending
// view won't be able to receive 'request' signal
view = new Backbone.View({collection:collection}); // at this point collection.length == 0
// view did not receive the 'request' signal, therefore has no idea that the collection is fetching
// and the view should render 'loading'
// after 2 seconds, 'sync' signal gets sent
View should not assume that if collection.length == 0 then it is unfetched.
View should also not assume that it is given collection in unfetched state (or in any other state).
If we want to decouple collection from view, then view has to be able to know what is the collection state.
the same thing goes for the Model
@g00fy If you can't just fetch
the collection after sending it to the view, set a fetching
flag or such on your collection.
collection.on({
request: function () { this.fetching = true; },
'sync error': function () { this.fetching = false; }
});
Now your view can access this.collection.fetching
and also wait for this.collection
to fire the sync
or error
event.
@caseywebdev
The request might be aborted, or two requests might get sent at once.
// example 1
collection.fetch().abort() // and collection.fetching == true
// example 2 - don't care about abort();
collection.fetch();
collection.fetch();
// 1st request compleated
!!collection.fetching == false // but the 2nd request is pending - should it be loading or not?
// 2nd request completed
The solution to this would be to connect do deferred xhr
collection.on({
'request':function(model,xhr){
this.fetching = true;
xhr.fail(function(){this.fetching = false }.bind(this));
},
'sync error': function () { this.fetching = false; }
});
That is why, I think this might be handy to have this built in, but on other hand, if every enhancement like this got through, BB code-base would be bloated.
if every enhancement like this got through, BB code-base would be bloated.
I think it's less about bloating than it is about approach. There are many different ways you might want to handle concurrent requests. Backbone provides you with the primitives that you need to handle them and then gets out of the way.
@g00fy- you might want to take a look into writing a finite-state machine for your purposes. Chaplin.js has one that should be pretty easy to replicate, and there's also ifandelse/machina.js (see the blog post) which may suit your specific use case.
Most helpful comment
@braddunbar , @caseywebdev the idea is to decouple those two parts. (view should be able to get collection in any state, not just _'clean'_ collection)
I am aware that I can do this using signals, but in many cases this can not be done this way. The order of actions matters
I agree that view should listen for 'request' and 'sync' signals, but the request signal might be sent before the collection is passed to the view, therefore view has no idea that the collection is fetching.
Consider an example, where your view gets an arbitrary collection. This collection can be either _fetched_ , _fetching_ or _unfetched_ when it is passed to the view (tl:dr see example 3).
Example 1 (where signals will work)
Example 2 (view gets already fetched, but emty collection, signals will also work)
Example 3 (most important, signals will not work)
View should not assume that if collection.length == 0 then it is unfetched.
View should also not assume that it is given collection in unfetched state (or in any other state).
If we want to decouple collection from view, then view has to be able to know what is the collection state.
the same thing goes for the Model