Parse Backbone Collection as Object, not Array - javascript

I implementing nested comments using Backbone and Rails. My current implementation on the server side involves comment models that store the parent_comment_id (assuming they have one). When the app requests the comments for a given entity, I return a JSON object where the keys are the parent_comment_ids and the values are arrays of comments that have that a parent comment with that id. E.g.:
{
"" : [{id: 1, content: "I'm an unnested comment, parent_comment_id: ""}],
1 : [{id: 2, content: "I am nested under the comment with an id of 1", parent_comment_id: 1}, etc.],
...
}
The problem that I am currently having is that the Backbone collection corresponding to Comments returns an Array of length 1, where the sole element is the comments hash.
How can I override the parsing of the JSON response by the Comments collection so that the returned response is the JSON response hash and not an array?

You can override collection.parse method

After some further consideration, I decided that the best course of action was to offload the construction of the comments hash to the client side. By doing this, I can continue to parse collections as Arrays of objects as intended and then build the hash by calling the following method on the collection:
Jot.Collections.Comments = Backbone.Collection.extend({
...
commentsByParent: function() {
var commentsHash = {},
key;
this.models.forEach(function(c) {
key = c.get('parent_comment_id');
commentsHash[key] = commentsHash[key] || [];
commentsHash[key].push(c);
});
return commentsHash;
}
});

Related

Most efficient way of extracting values from an array and passing to an ajax Post call

Currently I am calling ajax and posting the following object as data:
var answer = {
checklist: {id: 1},
question: {id: questionId },
answer: "testing1",
notes: checkInNotes
};
On the server side, this updates the answer and notes in the database where a question and checklist with the id of 1 are found.
Now say I have an array of questionId's that I need to pass in to ajax as part of that question property in that object above. What would be the best way to achieve this in ajax?
Currently I can achieve this by sending an ajax call off to the server x amount of times for each value that I need updated in the database, but this is obviously inefficient.
I'm quite new to ajax so please forgive my lack of knowledge.
Thank you for your time.
JSON allows arrays as well as objects.
You can include an array as one of your object properties (if that is what you need) and get it in the server.
var answer = {
checklist: {id: 1},
question: {id: questionId },
answer: "testing1",
notes: checkInNotes,
arrayOfQuestionId: [ 1, 2, 3, 4 ]
};
You could also send an array of objects instead of just one:
var otherAnswer = [ object1, object2, ... ];
tips: generate mix data and post all it to sever side.
1.send all requests from client
2.send all mix data to server and be parsed.
way1: from server
let url='*',ids=[1,2,3];
//generate paramse of array.
function getarams(){
let requests_params=ids.map(i=>{
let data_temp={question:{id:i}}
return data_temp;
}||[];
return resuests_params;
}
//be parsed from server
$.post(url,{data:getParams()},function(data,status){},'json');<br>
way2: send all posts once
let posts=getParams().map(d=>{
return $.post(url,d)
});
$.when(posts[0],posts[1],posts[2]).then(result=>{
console.log(result);
})

Backbone Collection: How to fetch a specific object from API to place in model

I am using a collection to fetch data from an API to place this into a model.
I do receive all data from the API, however the data is returned in an object and I only need a part of this object.
Let me clarify this with an example of the returned JSON:
{
"all-users":
[
{"username":"poekoe","lastsyncdate":"1376496898"},
{"username":"plaap","lastsyncdate":"1376494547"}
],
"total-users": "10",
"selected": 2
}
This is the JSON returned, however I only want need the 'all-users' array to be placed in my model.
At this point I am fetching data like this:
var userCollection = new UserCollection;
userCollection.fetch({
data: {
"search": "p",
"session: login.session
}
});
What can I do here to only use the 'all-users' array to be placed in the model?
Is there something in the Fetch what I can do? or should I alter the Model to only use the all-users array?
Thanks in advance!
You can override the parse method of the collection:
var UserCollection = new Backbone.Collection.extend({
parse: function(data){
return data["all-users"];
}
});
So your Collection will only consist of what the parse method returns, in this case the all-users array from your response json.

Backbone fetch and working with the jqXHR object

I'm working on a new application using Backbone and don't have the backend APIs written yet so I am trying work with a JSON data file local to my project. I set its location as the urlRoot and am able to fetch it and receive the jqXHR object back. But, I am not sure how to interact with the responseText (assuming that's what I need based on the console.log output of the object).
This is the closest question I've found to mine but it wasn't closed with a final answer: backbone model is only returning and object, or JSON {readyState : 1}
var JobListings = Backbone.Model.extend({
urlRoot: 'scripts/app/data/listings.json'
});
// Instantiate the model
var jobListings = new JobListings();
console.log(jobListings.fetch()); // Returns jqXHR object
console.log(jobListings.attributes); // Returns empty object
How do I get at my JSON data? Also, it should be in a model and not a collection right? I am a bit fuzzy as to the role of collections based on other developers use of them. I thought models contain data and collections were sets of models.
My goal was to build two models for the data. One takes in the dirty JSON that needs to be cleaned up and the second being my outputted clean data for use by the application. Any help is much appreciated.
EDIT:
A snippet of my JSON... I'm still not having luck on how to get at my data. I'm sure I don't have to get to a view to see my data before hand.
[
{
"jobId": "1",
"applyUrl": "http://google.com",
"title": "President of the World",
"trackingCode": "1",
"jobDescription": "Stuff",
"requiredSkills": "Stuff",
"requiredExperience": [],
"postingDate": "2013-07-12T11:07:50Z",
"jobLocation": {
"countryCode": "US",
"region": "California",
"municipality": "Santa Monica"
},
"category": "Life",
"businessUnit": [],
"positionType": "Full-Time"
}
]
'Backbone.Model' contains data
'Backbone.Collection' were set of models. Like you can define it as in below:
var Library = Backbone.Collection.extend({
model: Book
});
You normally won't work with jqXHR directly.
Once data is fetched, you can access it "field by field" (or attribute-by-attribute) using get operation:
note.get("title")
You can edit the data using the set operation:
note.set({title: "March 20", content: "In his eyes she eclipses..."});
book.set("title", "A Scandal in Bohemia");
You can return a copy of the data (called attributes) using toJSON operation
Also Backbone will track if data is dirty or not by using hasChanged
Looking at your code, JobListing will be a model with job listing data. JobListings would be a collection of all JobListing models:
var JobListing = Backbone.Model.extend();
var JobListings = Backbone.Collection.extend({,
model: JobListing,
url: 'scripts/app/data/listings.json',
parse: function(data) {
// Not sure about your json structure, but you could do the following
// Do your cleanup here
return data.joblistings;
}
});
// Instantiate the collection
var jobListings = new JobListings();
var req = jobListings.fetch();
req.done(function() {
// contains all job listings
console.log(jobListings.models);
});

Reading all object values in StackMob

I've been using StackMob's fetch() function to retrieve all objects in my table, given by the fetch() method as a single model object. Each object has multiple attributes with corresponding values. I've then used JSON.stringify(model) to get this output:
{"0":{"attribute1":val1,"attribute2":"val2","attribute3":val3,"attribute4":"val4"},
"1":{"attribute1":val1,"attribute2":"val2","attribute3":val3,"attribute4":"val4"},
"2":{"attribute1":val1,"attribute2":"val2","attribute3":val3,"attribute4":"val4"}
...and so on.
How can I print out just each of those values?
StackMob has a get() function that can be used as such:
var a_book = new Book({ 'title': 'The Complete Calvin and Hobbes', 'author': 'Bill Watterson' });
console.debug(a_book.get('title')); //prints out "The Complete Calvin and Hobbes"
But I'm not sure how I would use it in my situation, where I'm retrieving all of the objects in my table, rather than creating a new object (as above).
since the stackmob js sdk is built on backbonejs you could declare a collection which can contain all the "rows" in your "table" and then iterate through the collection to perform whatever action you want to each item in your "table"
var MyModel = StackMob.Model.extend({
schemaName:'YOUR_SCHEMA_NAME'
});
var MyCollection= StackMob.Collection.extend({
model:MyModel
});
var myCollection = new MyCollection();
myCollection.fetch({async: true});
myCollection.each(function(item){
//do something with item, maybe print
});

Fetch Backbone Collection by Model IDs list

I have a REST API serving a few URLs:
/rest/messages
provides all messages. A message is a JSON/Backbone Model
{
title: 'foo',
body : 'bar'
}
To get a single message I have:
/rest/messages/:id
Is it possible to fetch a Backbone Collection using message IDs array? I don't want the whole message list, but just a few messages I specify by ID.
I could fetch Models one-by-one and fill up the Collection, but I'm wondering if Backbone has a cleaner way to do this.
Thanks
According to documentation, you can pass ajax options to the fetch call. So, you can pass ids as data attribute to the fetch call being done and based on it, return the respective models from the server.
For example (when doing fetch),
collection.fetch({
data : {
message_ids : [1, 3, 5] // array of the message ids you want to retrieve as models
}
})
This message_id array will be accessible as parameters (not sure of the name in your case) in the server code being executed at /rest/messages, from there you can return only specific models based on ids you receive as message_ids. The only thing you need is, client side must be aware of the ids of all the message models it needs.
You can use any data structure instead of array to send message_ids.
The url property of collection reference to the collection location on the server. When you use fetch, backbone uses that url.
The url property can be also a function that returns the url. So you can do something like that:
var ids = [1,2,3]
var messages = new MessegecCollection();
messages.url = function() {
return "/rest/messages/"+ids.join("-"); //results "/rest/messages/1-2-3"
}
messages.fetch();
You can also create a method in your collection that generated and set the url, or even fetchs a set of models.
Now all you have to do is to support this url: /rest/messages/1-2-3
Hope this helps!

Categories

Resources