Backbone View Design - backbone.js

I'm trying to create a html page like this
Publisher (Master) - Use CompositeView
Book List (Detail) - User ItemView
Video List (Detail) - ????? 1. What to use for this detail ?????
Should I get all the data at once request or separate into 3 requests?
ABC Publisher
Book1, Book2, Book3...
Video1, Video2, Video3...

Your question pretty broad, but lets to clarify.
1) Shorty about view:
Publisher - CompositeView? It will be correct approach if you are going to render in this view PublisherModel or PublisherCollection. If this view just a wrap for child views, use LayoutView.
Book List - looks like you are going to render collection here, so you should use CollectionView or CompositeView instead ItemView. ItemView should be used in case you would like to render single model.
2) Common approach use separate request for each collection or model. In your case you should send request for video, another for books and so on. If you would like to get all data in one request u'd better to create something like Controller - it will be in charge to parse this request response and provide parsed data to special collections.

This seems like a great use case for backbone-relational. In your server side code you define your json to contain nested elements. So each publisher would have a book list and a video list that's returned in the json. Then backbone-relational will auto-parse those and create collections/models for you. So you could say publisher.get('books') and you'd get your books collection. You also can get a reference from your books in your book list to your publisher and so on. I find it's a great way to just make the one call and handle all of the other pieces from there.
So your publisher model code would be something like this (note - your keys should actually match your json):
class Entities.Publisher extends Backbone.RelationalModel
urlRoot: "publishers"
relations: [
{
type: Backbone.HasMany
key: "bookLists"
relatedModel: Entities.BookList
reverseRelation:
key: 'publisher'
includeInJSON: 'id'
},
{
type: Backbone.HasMany
key: "videoLists"
relatedModel: Entities.VideoList
reverseRelation:
key: 'publisher'
includeInJSON: 'id'
}
]

Related

Backbone Collection get property

Got a server returning a JSON object like so:
{
'key1':'value'
'key2':{
'key2_0':'value'
}
}
And a collection:
var Collection = Backbone.Collection.extend({
url:api.url//which returns the object above
});
var collection = new Collection();
collection.fetch({
success:function(data){
//do something
}
});
Now i need to use certain properties of the collection throughout my application, but say i need key1, i always have to do collection.at(0).get('key1');//returns 'value', because the data returned is stored within the collection, in a new Array at key 0.
Question:
How to directly... collection.get('key1')//now returns undefined... because it is.
I know i could expose an object to the global scope in the collection success function some_other_var = data.toJSON()[0] and access the some_other_var properties directly, but that's not what i'm looking for;
In order to use the get() function from a Backbone.Collection you need to know the model id or cid wanted.
For instance, lets say your data coming from the server is like follow:
[{
id: '123',
name: 'Alex'
}, {
id: '456',
name: 'Jhon'
}]
In that case you can do this:
this.collection.get('123').get('name') // Return "Alex"
Keep in mind that collection is just a set of model, so behind the scenes by doing collection.get() you are getting a model
Tip: If you don't have any kind of id in your server data, there is always the option of using underscore methods:
find
filter
some
contains
etc
It seems like you're trying to ascribe attributes to a collection, but a collection is merely a set of models. Having additional data that is constant throughout the collection suggests that it should be wrapped inside another Model, which is demonstrated here: Persisting & loading metadata in a backbone.js collection

Sencha Touch background syncing of store

I have a list that is bound to a store. I have a input text field (think chat like UX), and when the user clicks on a button, I do:
var newMessageData = {
text: textMessage
};
var message = Ext.create('MyApp.model.Message', newMessageData);
messagesStore.add(message); // At this point, the message shows up in my list
message.save(); // On a successful save, an identical message shows up again in this same list
How can I implement this, so the message only shows up once at first (immediately after the user types in something) and then the record itself just syncs with the server in the background.
Help is much appreciated! Thanks!
Edit:
My model definition is pretty simple with simple fields and a few converted fields + a custom idProperty:
idProperty: 'objectId',
{
name: 'objectId',
persist: false
}
You should be able to use messagesStore.sync() which:
Synchronizes the Store with its Proxy. This asks the Proxy to batch
together any new, updated and deleted records in the store, updating
the Store's internal representation of the records as each operation
completes.
http://docs.sencha.com/touch/2.4.0/#!/api/Ext.data.Store-method-sync
Okay, so what was missing was that I had to add the keys "primaryKey" to my hasMany and belongsTo relationships. In my case, I had idProperty: 'myCustomId', but that alone didn't work for associated models. I had to add primaryKey: 'myCustomId' to my hasMany and belongsTo relationships.

Backbone.js Dynamic model creation based on JSON received from the server

I am trying to create a backbone client side application. I am receiving a list of json objects from the server on startup that will be a list of the possible tables exposed from the server, with their structure. E.g. Customers, Orders, Invoices, Employees
I want to create the models, collections and views dynamically based on the data I receive from the server.
Only when I receive the json on load will I know what the models should be and what the relationships between the models should be.
E.g. Customers structure might be Id, CustomerName, Address, Contact Numbers.
Order Structure might be Id, CustomerId, OrderDate, Amount
etc
By building Models, collections, views, controllers dynamically, I could in theory on startup point at another server who might give me a totally different set of tables e.g. : Movies, Actors etc.. with their structures.
Also, if additional fields are added I don't have to change the client side code again. E.g. Customer table might include a new field called ContactPerson
Please assist me as all the examples I saw on backbone is all based on statically defining the models on the client side up front. So create a model and collections and views for Customers, Orders, Invoices, Employees etc. etc.
Best wishes,
Andy
As already mentioned in the comments, Backbone models are dynamic by nature. So this is perfectly valid for example:
// A example dataset, this could be returned as JSON from the server
var jsonDataA = [
{
name: "Foo",
title: "Bar"
},
{
name: "a",
title: "b"
}
],
// A different example dataset
jsonDataB = [
{
make: "X",
model: "Y"
},
{
make: "Z",
model: "ZZ"
}
],
MyModel = Backbone.Model.extend({
/* Empty Model definition */
}),
MyCollection = Backbone.Collection.extend({
model: MyModel
}),
collection = new MyCollection();
collection.reset(jsonDataA);
console.log(collection.models);
collection.reset(jsonDataB);
console.log(collections.models);
Here I have reused the same Collection and Model definition to store completely different datasets.
One part is the raw data, the other part is its relations. You need to transport the metadata also, which contains the types and their relations. Model attributes will be populated automatically.
From your metadata a simple object can be constructed, where the keys describe one entity, for example:
var entites = {};
entities["Customer"] = Backbone.Model.extend({
/* Model definition based on metadata */
});
var parametersFromServer = {name: "John Doe"};
var customer = new entities["Customer"](parametersFromServer);
For building relations I would recommend using BackboneRelational plugin.

Will calling fetch on my Collection instantiate all of the Models it receives in Backbone?

I have this code in my Backbone application:
app.Collections.quotes = new app.Collections.Quotes();
app.Collections.quotes.fetch();
And I can see an array of Objects returned in the network tab but when I expand out the Collection, the Models array inside is 0. Do they get instantiated as Models when fetch() is ran on a new Collection?
This is my Collection:
app.Collections.Quotes = Backbone.Collection.extend({
model: app.Models.Quote,
url: function() {
return app.Settings.apiUrl() + '/quotes';
}
});
EDIT:
app.Collections.quotes.fetch({
success: function(){
app.Utils.ViewManager.swap('section', new app.Views.section({section: 'quotes'}));
}
});
And in my Model:
idAttribute: 'Number',
This was the fix! Thanks for help. Dan kinda pointed me in the right direction amongst the comments...
Calling fetch() on a Collection attempts to populate the JSON response into Models: Collection#fetch.
Is your server definitely returning a valid JSON array of objects?
Do you have any validation on your Quote Model? I'm pretty sure Backbone validates each models before populating the collection, only populating with the models which pass. So if it exists, check that your Model#validate method is working correctly.
You shouldn't need an ID (although it's obviously required if you want to edit them).

AppEngine Datastore get entities that have ALL items in list property

I want to implement some kind of tagging functionality to my app. I want to do something like...
class Item(db.Model):
name = db.StringProperty()
tags = db.ListProperty(str)
Suppose I get a search that have 2 or more tags. Eg. "restaurant" and "mexican".
Now, I want to get Items that have ALL, in this case 2, given tags.
How do I do that? Or is there a better way to implement what I want?
I believe you want tags to be stored as 'db.ListProperty(db.Category)' and then query them with something like:
return db.Query(Item)\
.filter('tags = ', expected_tag1)\
.filter('tags = ', expected_tag2)\
.order('name')\
.fetch(256)
(Unfortunately I can't find any good documentation for the db.Category type. So I cannot definitively say this is the right way to go.) Also note, that in order to create a db.Category you need to use:
new_item.tags.append(db.Category(unicode(new_tag_text)))
use db.ListProperty(db.Key) instead,which stores a list of entity's keys.
models:
class Profile(db.Model):
data_list=db.ListProperty(db.Key)
class Data(db.Model):
name=db.StringProperty()
views:
prof=Profile()
data=Data.gql("")#The Data entities you want to fetch
for data in data:
prof.data_list.append(data)
/// Here data_list stores the keys of Data entity
Data.get(prof.data_list) will get all the Data entities whose key are in the data_list attribute

Resources