Backbone-relational between two models - backbone.js

By using Backbone-relational I would like to have the model task in this way:
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: userModel
};
I did try this way (1) but the result is the following (2).
Any ideas?
(1)
var User = Backbone.RelationalModel.extend({
// urlRoot
});
var Task = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasOne,
key: 'user',
relatedModel: User
}
],
// urlRoot
});
(2)
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: null // null instead of having something related to user model
};

Not sure what your the exact JSON is for your Task model, so I'm guessing here.
Backbone-relational is expecting either a fully nested model:
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: {
name: 'Fred Rogers',
id: 42,
occupation: 'Hero'
}
};
Or a string/number, which it will assume to be the id of the related model:
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: 42
};
I'm guessing you're hitting the second case, based on the null value you're getting for the user model.
When backbone-relational instantiates an instance of a model, and the related model is a "key" string/number, it will search its internal store of models to try to find a matching model. If it finds it, it sets that model as the value for the user property.
If it cannot find the model, it stashes the key in the model's relevant relation property model._relations[n].keyContents, and sets the user value to null.
It is at this point that you would use the fetchRelated function to get the related model from the datastore/API.
So, try calling task.fetchRelated() to get the related user model:
task.fetchRelated('user');

Related

Angular-Formly Nested Model Not Updating

I am having an interesting issue with angular-formly. I am attempting to use the 'model' tag as shown below because my model is not flat.
{
'key': 'last',
'model': 'model.name',
'templateOptions: {}
}
However, I cannot update the model in a clean manner. Simply replacing model or even model.name with a matching model that contains the updated value does not cause the model to update the view.
var newModel = {
name: {
first: 'Gandalf',
last: 'The White'
}
};
self.model = {
name: {
first: 'Gandalf',
last: 'The Grey'
}
};
function setNewLastName() {
self.model = newModel;
}
setNewLastName();
However if I drill down to the specific property, it works as expected.
self.model.name.last = self.newModel.name.last;
Here is a link to a JSBin where the value updates using the drill-down method immediately above.
Drill-down JSBin
Another JSBin that attempts to update the model by assigning a new model that does not update.
Assign Model JSBin
Has anyone ran into this issue or can you see where I'm doing something wrong?
You replace the model for each key, therefore you never see the changes.
What you need to do is to match the model in the key itself.
vm.fields = [
{
key: 'name.first', // <-- HERE
type: 'input',
//model: vm.model.name, //Wrong
templateOptions: {
label: 'First Name'
}
},
{
key: 'name.first', // <-- AND HERE
type: 'input',
//model: vm.model.name, //Wrong
templateOptions: {
label: 'Last Name'
}
},
//...
];
See corrected example: http://jsbin.com/pupijoc/1/edit?js,console,output
UPDATE: Nested properties are also handled by fieldGroups
Se updated example: http://jsbin.com/pupijoc/3/edit?js,console,output

Collection inside a Backbone model

I want to create a Backbone model and store a collection of another model into its property. So, there are parent and child model. Each parent has one or more children stored as an array inside its property.
The JSON will be like this.
Parent = {
name: 'Name',
age: 'Age',
children:
[{name: 'Name', age: 'Age'},
{name: 'Name', age: 'Age'},
{name: 'Name', age: 'Age'}]
}
I've tried to create both model and insert one inside the other but still has no solution. And I don't want to use parse or other server things.
So, is there any solution or better way to achieve that?
As I understand you want to create a model with this data and if there are children inside model to make a collection of same models inside.
var Person = Backbone.Model.extend({
initialize: function(){
this.set('children', new Persons(this.get('children')));
}
});
var Persons = Backbone.Collection.extend({
model: Person
});
On the model creation - initialize: function () {...}
Lets take our children array - this.get('children')
And make a collection - new Persons(...)
Collection will create models itself
And put everything back - this.set('children', ...);
JSFiddle - run and see result in console.

ExtJS 4 I don't understand models + associations

I don't think the documentation is very clear on this - at least I can't figure out how associations work with models in ExtJS 4. Lets look at a simple example:
the models
Ext.define('app.model.Goo', {
...
fields: ['id', 'foo_id', 'goo_field'],
belongsTo: 'Foo'
});
Ext.define('app.model.Foo', {
...
fields: ['id', 'foo_field'],
hasMany: {model: 'Goo', name: 'goos'} //
});
this allows me to easily write a server response that returns nested data such as:
{
success: true,
foo: {
id: 42
foo_field: 'bacon',
goos: [
{ id: 0, goo_field: 'velociraptor' },
{ id: 1, goo_field: 'spidermonkey' },
...
]
}
}
and parse out the data into their respective models. But what if I want to load nested data lazily? Say I write my server such that it doesn't send any goos field in my returned foo object. What does it mean to write foo.goos().load()? What's being sent to my server then? GET <proxy:url>/<'id' of foo>/goos ?
If you want to lazy load goo you should not send goo in the foo response. But instead you call foo.goos(). This wil return a goo store with a filtervalue foo_id on 42 (primary id from your foo instance). Basicly its doing something like this for you:
Ext.create('Ext.data.Store', {
model: 'app.model.Goo',
filters: [
{
property: 'foo_id',
value: 42
}
]
});
So calling load does the request. Assuming you are using REST proxy, your goo proxy will do the following request: GET <proxy:url>with filter-queryparameters: filter:[{"property":"foo_id","value":42}].
Also I believe you need to specify fully qualified class name (ie. model: 'app.model.Goo').

Backbone Collection Set method remove existing elements and then add all elements

I have a backbone collection.I want to add or remove some models dynamically in the collection. But if i am using collection.set() method then it is going to remove first all elements and then it will add all elements again.
What i want to do is trigger add event of collection for those whose are really new added and trigger remove events for those whose are removed from previous collection.
Here is a example [http://jsfiddle.net/PkJCx/2/]
From the docs
The set method performs a "smart" update of the collection with the
passed list of models. If a model in the list isn't yet in the
collection it will be added; if the model is already in the collection
its attributes will be merged; and if the collection contains any
models that aren't present in the list, they'll be removed.
It is also a good idea to provide `idAttribute' to the model so that the collection identifies that based on the id. Otherwise the collection would not know if the model is a new one or not.
So after setting the id and using set, you can see that is performs a smart update
$(function () {
var MyModel = Backbone.Model.extend({
// This attribute should be set as a default
defaults: {
Name: ''
},
// Set the id attribute so that the collection
// know that it is the old model
idAttribute: 'id'
});
var Coll = Backbone.Collection.extend({
model: MyModel
});
var models = [{
Name: 'A',
id: 1
}, {
Name: 'B',
id: 2
}];
var collection = new Coll(models);
collection.bind('add', function (model) {
alert('addb')
});
collection.bind('remove', function () {
alert('add')
});
models = [{
Name: 'A',
id :1
}, {
Name: 'B',
id: 2
}, {
Name: 'C',
id: 3
}];
collection.add(models);
});
Check Fiddle
It will not try to remove the other 2, but Backbone is smart enough to identify that 2 of them are old models and then just merges the newer one into the collection.

backbonejs - fetching multiple model

i'm novice in backbonejs and i'm doing some project that includes fetching and displaying friends list. for this project i'm using parse.com as database. but i'm stocked at this point.
for example: i have following data's in user and friends models.
var user = [
{
id: 'x1',
firstname: 'Ashik',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'xyz#gmail.com'
},
{
id: 'x2',
firstname: 'rokesh',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'rokesh#gmail.com'
},
];
var friends = [
{
user_id: 'x1',
user_friend_id: 'x2'
},
{
user_id: 'x1',
user_friend_id: 'x4'
},
{
user_id: 'x1',
user_friend_id: 'x10'
},
{
user_id: 'x2',
user_friend_id: 'x25'
}
];
// collections
var userCollection = Backbone.collection.extend({
model: user
});
var friendListCollection = Backbone.collection.extend({
model: friends
});
var friends = new friendListCollection();
now what i want?
when i fetch friends collection object, i want to get friends list of user with their details.
example::
friends.fetch({
success: function(ob){
var ob =ob.toJSON();
// i want ob to be like
[
{
id: 'x2',
firstname: 'rokesh',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'rokesh#gmail.com'
},
{
id: 'x4',
firstname: 'rokesh',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'rokesh#gmail.com'
},
{
id: 'xx10',
firstname: 'rokesh',
lastname: 'shrestha',
phone: '12321321',
mobile: '123213',
email: 'rokesh#gmail.com'
},
]
}
});
should i create new collection to relate them or is there any other way to do this??
Thanks in advance!
To use the least of server requests to gain a better performance and less presure on server side, I would suggest you to add this logic on your server-side rather than here on client-side. e.g. When fetching with parameters like ?detail=true, the server then return simple information with detailed data, otherwise only return simple information.
If you have a good reason to seperate them into different Collections, you have to fetch those collections consequently.
Assuming you do not wish to change your data structure, you can use BackboneJS' model's idAttribute property, to retrieve a specific model from a collection by a specific key, usually an "id".
When you define your model, you should also define the idAttribute for the model, which will later allows your to access it from the collection, by the value of this field.
When a Backbone collection is synced, all models are parsed according to their defined structure, adding administrative functionality on top of their data.
Consider the following example:
var myModel = Backbone.Model.extend({
idAttribute: "id"
...
});
var myCollection = Backbone.Collection.extend({
model: myModel
...
});
Once myCollection holds one or more "myModel"(s) you can then simply use the following:
var myModelFromMyCollection = myCollection.get(id);
the idAttribute of the model can by any of the model's fields...
For your use case, lets assume both friendListCollection and userCollection are already available and have models in them, consider the following code to get the full details of each friend from it's user model like so:
friendListCollection.each(function(friendModel) {
var friendFullDetailsFromUsersCollection = userCollection.get(friendModel.id);
console.log(friendFullDetailsFromUsersCollection);
...
});

Resources