I'm new to backbone and I'm trying to set a collection of models with data loaded from a json-file. But it won't get set. Whats the problem here? Anyone having an idea? When i fetch the collections it seems that its empty.
JSON
{
"items": [
{
"id": "0",
"media": "",
"desc": "lorem",
"img": "ipsum"
},
{
"id": "1",
"media": "",
"desc": "lorem",
"img": "ipsum"
}
]
}
Javscript
var Card = Backbone.Model.extend({
defaults: function() {
return {
items: {
id: "lorem",
media: "lorem",
desc:"lorem",
img: "lorem"
}
};
},
clear: function() {
this.destroy();
}
});
var CardCollection = Backbone.Collection.extend({
model: Card,
url: "file.json",
parse: function (response) {
for (var i = 0; i<response.items.length; i++) {
}
}
});
var cards = new CardCollection();
cards.fetch();
console.log(cards)
fetch is asynchronous, it returns immediately before the data has been loaded.
Try this
var cards = new CardCollection();
cards.fetch({
success: function () {
console.log(cards);
}
});
The CardCollection.parse method is called with the response. If no transformation is required to the response from the server, you can remove the parse method of the CardCollection. The default implementation is pass thru and the response is used as-is.
Basically parse should return the array to be added to the collection. The current implementation does not do anything. return is missing for the implementation.
Just return something from your parse method and you are good to go. It is expected to return an array of objects and each object will fit into your model. So finally you will have a collection of models corresponding to array of objects being returned from parse method.
Try this
var CardCollection = Backbone.Collection.extend({
model: Card,
url: "file.json",
parse: function (response) {
return response.items;
}
});
Read this Documentation on Parse Method for more information.
Related
Say i have the following function:
getImageText(base64Image) {
const body = {
"requests": [
{
"image": {
"content": base64Image
},
"features": [
{
"type": "TEXT_DETECTION"
}
]
}
]
};
return this.http.post('https://vision.googleapis.com/v1/images:annotate?key=' + environment.googleCloudVisionAPIKey, body);
}
Now when this succeeds it returns the following: {responses: [], text:'' }
So in short it returns an object with a response array and a text string
Now my first attempt was to set the following return type:
getImageText(base64Image): Observable<{ responses: any, text: any }>
However i am not sure this is the right way of doing it.
Also my console gives me an error. And what happens when this promise returns an error then the object is different.
So my question is what is the correct way of making a return type on methods that are using http / promises
Your method getImageText(base64Image) may return an Observable. However, your current implementation isn't returning one. You can convert a promise into an observable as such.
getImageText(base64Image): Observable<{ responses: any, text: any }> {
const body = {
"requests": [
{
"image": {
"content": base64Image
},
"features": [
{
"type": "TEXT_DETECTION"
}
]
}
]
};
return from(this.http.post('https://vision.googleapis.com/v1/images:annotate?key=' + environment.googleCloudVisionAPIKey, body));
}
And then you can subscribeto this method where you need to.
function DoSomethingWithTheResponse(){
getImageText(yourBase64Image).subscribe(
value => {
//do something with the value
});
}
I have a javascript object with nested objects obtained by a plugin saved in a variable called 'json':
// var json:
Object {0: Object, 1: Object}
0: country
countryCapital: Object
ministers: Array[1]
1: country
countryCapital: Object
ministers: Array[3]
// Should be restructured to fit MVC models
World
Country Array [2]
Capital: Object
Minister: Array [1]
Because I'm sending the data using jQuery-ajax to a MVC controller I'm trying to rename/restructure them to bind them to a MVC Model so I can send the whole 'World' object as 1 parameter.
// Controller
[HttpPost]
public void Save(World world)
// Model structure:
World
* Country (list)
1 Capital
* Minister (list)
How do I convert the javascript object to the right structure that fits the Model parameter? Do I need to loop everything or can it be done in a better way?
UPDATE:
json object update, it's a lot of data so I simplified it.
// World
{
"0": { // Country
"ministers":
{
"objects": [
{
"name": "name1"
},
{
"name": "name2"
}
]
},
"countryCapital": {
"name": "...",
}
},
"1": { // Country
"ministers":
{
"objects": [
{
"name": "name1"
},
{
"name": "name2"
}
]
},
"countryCapital": {
"name": "...",
}
}
}
I suppose you're searching for $.map().
At the background it's looping your collection but it much cleaner to use it in your case.
Updated to use your example json. Jsfiddle
var world = {}
for (var countryIteration in originalObject) {
var country = originalObject[countryIteration];
world[countryIteration] = { //you need to this because you need dynamic keys.
capital : country.countryCapital.name,
ministers : country.ministers.objects
}
}
I found a working solution thanks to teo van kot using jQuery map.
var world = {}
$.map(json, function (value, i) {
if (i == "countryCapital") {
world.Capital = value
}
if (i == "ministers") {
world.Minister= value
$.each(value, function (j, minister) {
world.Minister[j].Name = minister.name;
delete minister.name;
});
}
}, world);
I'm trying to deal with a server response, and am a little confused how to turn the json response into Backbone Models.
My Backbone model looks like so:
Entities.Recipe = Backbone.Model.extend({
defaults: {
id: '',
name: '',
introduction: ''
},
parse: function (response)
{
if(._isObject(response.results)){
return response.results
else {
return response
}
})
Entities.RecipeCollection = Backbone.Collection.extend({
url: 'recipes',
model: Entities.Recipe
)}
var API = {
getRecipeEntities: function (){
var recipes = new Entities.RecipeCollection()
var defer = $.Deferred()
recipes.fetch({
url: 'http://3rdpartyApilocation.com/recipes'
success: function (data) {
defer.resolve(data)
}
})
var promise = defer.promise()
$.when(promise).done(function (fetchedData)
{})
return promise
}
RecipeManager.reqres.setHandler('recipe:entities', function()
{
return API.getRecipeEntities()
}
And the response.results is an Array of objects - with each object having an id key, a name key and an introduction key. But because I am so inexperienced with Backbone I have no idea how to map those results to the model?
I have installed Chromes Marionette inspector and when I look at the entire array of results seems to be passed to the model, rather than each individual object within each response.result being set to each individual model. Sorry if I can't be more clear - I'm very new to Backbone...
Perhaps your confusion is because you're in fact able to use parse on a model or on a collection. And from your explanation it looks like the response.results object returns a list of objects that you want to become models in your application. But because you're catching that object in a model, the model doesn't know what to do with that array.
Let's say you have a response like this:
{
"status": "ok",
"results": [
{
"id": 1,
"name": "Pie"
}, {
"id": 2,
"name": "Rice"
}, {
"id": 3,
"name": "Meatballs"
}
]
}
Then you would just use parse on your Collection to let it know the response isn't array itself, and help it find it in the results property.
Here's a working example:
var Recipe = Backbone.Model.extend();
var Recipes = Backbone.Collection.extend({
model: Recipe,
url: 'http://www.mocky.io/v2/56390090120000fa08a61a57',
parse: function(response){
return response.results;
}
});
var recipes = new Recipes();
recipes.fetch().done(function(){
recipes.each(function(recipe){
/** Just demo of the fetched data */
$(document.body).append('<p>'+ recipe.get('name') +'</p>');
});
});
<script src='http://code.jquery.com/jquery.js'></script>
<script src='http://underscorejs.org/underscore.js'></script>
<script src='http://backbonejs.org/backbone.js'></script>
I am trying to load the value from the local sqlite dB (which I have tested and the values are there) into a global model that I can use in my views. When I try to print the values of the model after creating it using Ti.API.info(library.at(i));in index.js, it returns undefined most of the time and sometimes a function call like function lastIndexOf() { [native code] }. What is going on and how can I fix it? Here is my model (UpcomingRaces.js):
exports.definition = {
config: {
columns: {
"Name": "string",
"Location": "string",
"Date": "string",
"Url": "string"//,
//"Id" : "INTEGER PRIMARY KEY AUTOINCREMENT"
},
defaults: {
"Name": "string",
"Location": "string",
"Date": "string",
"Url": "string"
},
adapter: {
type: "sql",
collection_name: "UpcomingRaces",
//idAttribute: "Id"
}
},
extendModel: function(Model) {
_.extend(Model.prototype, {
// extended functions and properties go here
});
return Model;
},
extendCollection: function(Collection) {
_.extend(Collection.prototype, {
// extended functions and properties go here
comparator: function(UpcomingRaces) {
return UpcomingRaces.get('Name');
}
});
return Collection;
}
};
Here is how I am reading it into a model (index.js):
var library = Alloy.Collections.UpcomingRaces;
library.fetch();
function prepareView()
{
// Automatically Update local DB from remote DB
updateRaces.open('GET', 'http://fakeurl.com/api/UpcomingRaces');
updateRaces.send();
library && library.fetch();
// Read DB to create current upcomingRaces model
// Insert the JSON data to the table view
for ( var i in library ) {
Ti.API.info(library.at(i));
data.push(Alloy.createController('row', {
Name : library[i]['Name'],
Date : library[i]['Date']
}).getView());
}
$.table.setData(data);
}
Also I've got this in my alloy.js file
Alloy.Collections.UpcomingRaces = Alloy.createCollection('UpcomingRaces');
the problem is with your for loop:
// Insert the JSON data to the table view
for ( var i in library ) { // i here is an instance of the Model, not an index
Ti.API.info(library.at(i)); // <-- error here
data.push(Alloy.createController('row', {
Name : library[i]['Name'],
Date : library[i]['Date']
}).getView());
}
no need to call library.at(i), just use i element. So the correct code would be:
// Insert the JSON data to the table view
for ( var element in library ) {
Ti.API.info(JSON.stringify(element));
data.push(Alloy.createController('row', {
Name : element.get('Name'),
Date : element.get('Date')
}).getView());
}
I try to use backbone in my project. But I have met problem when try to overide parse method of Backbone. The server has send back more data than I want.For example:
What I want is:
[{
id: "123",
name: "david"
},{
id: "456",
name: "kevin"
}]
but the server's result is :
{
total: 1000,
items:[{
id: "123",
name: "david"
},{
id: "456",
name: "kevin"
}]
}
so I want process result in parse method and return only the array. How can I do this? When I try I got error. How should I do?
In your backbone model, define the parse function the way you would like:
Model = Backbone.Model.extend({
parse: function () {
return {
id: this.get("id"),
name: this.get("name")
}
}
});
But, it would be better to handle and set the data in the model initializer, like so:
Model = Backbone.Model.extend({
initialize: function (attrs) {
try {
//TODO HERE: test for correct values and throw errors
// set object variables here
this.set({
name: attrs.name,
id: attrs.id
});
} catch (e) {
console.log(e);
}
}
});
No need to overwrite the parse function now. This way you know the data that your model is handling is good, and you set what variables it contains. This avoids many errors from invalid data.
Each item in the array should really be a submodel, which is what I have written above. Your parent model should look like:
Model = Backbone.Model.extend({
initialize: function (items) {
this.subModels = [];
items.forEach(function (item) {
this.subModels.push( new SubModel(item) )
});
}
});
Or as a collection:
Collection = Backbone.Collection.extend({
model: ItemModel,
});
To which you would pass response.items
From Backbone Parse docs
Collection = Backbone.Collection.extend({
model: YourModel,
parse: function(response){
return response.items;
}
});