Passing additional variable in collection data - backbone.js

I made posts feed with button which loads 10 more posts onClick. The problem is I don't know when to hide that button if there are no posts left.
So I think I need to pass aditional variable in collection data (received from JSON), which tells to backbone there are more posts or not. How to receive this variable from the collection? Is it right thing to do?
Maybe there are better ways to do that without additional call to database?

If you absolutely need to avoid another service call, wrap your collection API response in a wrapper element which tells whether there are more posts.
GET /posts :
{
more: true,
posts: [
{id:1, title:"..."},
{id:2, title:"..."},
{id:3, title:"..."},
]
}
And use Collection.parse to unwrap the data:
parse: function(response) {
this.more = response.more;
return response.posts;
}
So you can check it from the collection:
if(collection.more) {
//..
}
However if your data is volatile, i.e. it would be possible for new posts to be created while the user is on the page, this would mean that the user would not be able to load more posts, after they have once reached the end of it.

Related

angular resource clears object data after post

my angular app clears data after post.
Here is the snippet from controller:
$scope.saveDevice = function() {
var deviceId = $scope.device.id;
if (deviceId) {
$scope.device.$update(function(result) {
$location.path('/devices');
});
} else {
$scope.device.$save().then(function (deviceResult) {
$scope.device.id = deviceResult.deviceId;
$scope.device.$activationCode(function (result) {
$scope.device.activationCode = result.activationCode;
});
});
}
};
When I hit break point at
"$scope.device.$save().then(function (deviceResult) {" the application shows that device is populated with properties from form. But after the post, device is cleared of any properties. Is this normal behaviour? If so, how can I prevent it?
Here I found the answer to my problem:
AngularJS - Prevent Form Clear
Basically:
call class method
Device.save($scope.device) //....
instead of
$scope.device.$save
and it will presist the data you've in $scope.device class.
I'm not sure if this helps, but from the docs. This is too long to put as a comment.
Angular Doc
It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data. This is a useful trick since usually the resource is assigned to a model which is then rendered by the view. Having an empty object results in no rendering, once the data arrives from the server then the object is populated with the data and the view automatically re-renders itself showing the new data. This means that in most cases one never has to write a callback function for the action methods.

backbone model toJSON strangely cache itself

I am still new to backbone:
Here is my problem that I find hard to explain:
on initialisation there is a model something like this:
Model:
{
Id:xxx,
Questions:
[
{
Id: "yy",
Selections:
[
{OptionId:"aaa"},
...,
{OptionId:"zzz"}
]
},
....
]
}
there is a event method updates Selections Collection.
After event triggers I got two different result by with two code below:
window.pkg.Questions.get(this.Id).Selections.reset(selectedoptions);
console.log(window.pkg.Questions.get(this.Id).Selections.toJSON());
console.log(window.pkg.Questions.get(this.Id).toJSON().Selections);
The first log shows the updated model, however the later shows initial default value.
why it is working like this?
They are two different copies. Your QuestionModel has a SelectionsCollection property called Selections, and a Backbone attribute, also called Selections. I assume you want to use the SelectionsCollection, and the attribute will not stay in sync with that. The attribute is the original json which I assume was inadvertently added to the model.
Hard to say exactly how to fix it, because you did not show the code where you create and fetch these models and collections. Wherever you take the Selections JSON and and initially reset it into the collection, you can remove it from the JSON and/or unset it on the QuestionModel if it is already there....
This would also print the wrong, original data:
console.log(window.pkg.Questions.get(this.Id).get('Selections')); // print original JSON
You can remove it in QuestionModel's parse:
parse: function(data) {
// removing Selections from data here will prevent
// it from being added as an attribute.
delete data.Selections;
return data;
}
If you do this, and you want the Selections to be included in the toJSON output of QuestionModel, you would also need to override toJSON.
toJSON: function() {
// get json for Question
var json = Backbone.Model.prototype.toJSON.call(this);
// add updated json for selections
json.Selections = this.Selections.toJSON();
return json;
}

How can i sort after i done the fetch in backone.js

On click of the 'sort by age', i am calling a function to fetch data from server and sort by age value. i do this after i done the fetching, but it result nothing and return all..
any one give a correct way to implement this?
my code:
this code in the view class,
sortByAge:function(){
this.collection.fetch() //fetching new collection
.done(function(data){ // once done i am passing data
var filterType = data.sort('age') // correct way need to sort.
that.collection.reset(filterType); // refreshing the collection
})
},
If before doing a fetch you're already aware that you need collection to be sorted by some specific column, from the docs, we can pass ajax options to the fetch. So fetch might look like this:
this.collection.fetch({
data: {
sort_by: "age"
}
});
sort_by parameter will be available in the server code being executed at the specified url for the collection, so you can return data from the server sorted by sort_by column. And then may be listen to reset event to do some work.
And if you want to sort collection after getting it on the client side may be you can look at these similar questions.
Sorting a Backbone Collection After initialization
Proper way to sort a backbone.js collection on the fly

Where does information in BackBone go?

When a save, or create is tossed towards the server, the server responds with a new randomly created object. The object can be one of many different Classes, and Backbone responds to these differentiating objects and loads a relative view.
I can only seem to figure this logic out on bootstrap, as no view has been loaded yet, so I can based on what information I am randomly receiving from the server, bootstrap and navigate to that specific route.
However, I am stuck on trying to figure out how to do this when I save an object, and receive my return data.
Here's my code broken down.
The information is saved.
#model.save(#model.toJSON(),
I have a listenener waiting for this save :
constructor: (options) ->
super(options)
#model.bind 'change:verb', _.chooser, options
_.maestra_chooser is a mixin I have in a utility belt :
_.mixin
_chooser : (item) =>
console.log item
Something to note here. The variable item is unfortunately, the same #model that was just saved. No new data there.
What I'm hoping for item to be is the new variable data from the server, so that I can take that data, see what kind of data it is, and then route to the relevant view.
This is where I believe I'm also making an architecturally unsound idea. But for reasons I don't understand enough to explain.
Does anyone know where I can access the return data from the server and appropriately navigate my app to that respective route?
Additional Information
This is how I bootstrap it appropriately :
window.router = new Project.Routers.QuestionsRouter(
{
words: #{ #words.to_json.html_safe }
});
Backbone.history.start();
router.navigate("#{#words.kind_of?(Array) ? "bar" : "foo"}", {trigger: true, replace: true})
The change event is only ever going to give you the model and the value that changed...
You can pass a success callback to your save:
#model.save(#model.toJSON(), success: (model, resp) ->
# do whatever with resp
)
where resp will contain the raw response from the server and model will contain the server side state of your model.
You can also bind to your model's sync event as mentioned in the comments:
#model.bind 'sync', _.masetra_chooser, options
the sync callback is called with arguments: model, resp and options where options is the set of options passed to save.
https://github.com/documentcloud/backbone/blob/9a12b7640f07839134e979b66df658b70e6e4fe9/backbone.js#L383
Not really sure why you are expecting to get data back from a save that'll change your page though. Seems a bit odd.
What type of data are you expecting to receive after a save that wouldn't be in your model?

ExtJS 4 URL is undefined when I try store.load()

I have a Panel with multiple grids. I'm trying to make some kind of global refresh button by which I mean, a button that will refresh all the grids and open tabs, without losing data like when F5 is pressed.
With two of the grids it was easy just get the store and load it but the third one makes a problem. When I try the same as with the previous two which works OK I get URL is undefined.
Here is my code:
reloadInstructionsStore: function() {
var reloadInstructionSt = this.getStore('Instructions');
var activeCat = this.getActiveCategory();
reloadInstructionSt.clearFilter(true);
reloadInstructionSt.filter({
filterFn: function(item) {
return item.get('category_id') == activeCat;
}
}),
reloadInstructionSt.load();
},
The only reason I can think of is that the store that I use here is defined different from the other 2. It's not with PROXY and CRUD, but looks like this:
Ext.define('MY.store.Instructions', {
extend: 'Ext.data.Store',
model: 'MY.model.InstructionRecord',
autoLoad: true,
data: g_settings.instructionsApi.initialData
});
Is the problem here and is there a way to make things work even like this?
Thanks
Leron
You do not need to reload this store, the data is provided on initial page load. The variable g_settings.instructionsApi.initialData tells me that the data is available as static on the page. All you need to do in this case is reset the filter, and just remove the reloadInstructionSt.load(); call.
If you actually do want the data to reload from the server, you will need to give your store a url that it can get the data from and the server will have to be able to serve this data up.

Resources