Collection inside a Backbone model - backbone.js

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.

Related

Loading Model from another model file in extjs

formGrid=me.abstractComponent.query('grid[itemId=grid]')[0],
Objmodel= Ext.create('Ext.document.model.GridModel');
formStore = Ext.create('Ext.data.Store',{
model:Objmodel,
data: data
});
formGrid.bindStore(formStore);
formStore.load();
I've been trying to load the store using the model, but error occurs saying that model not found. Is there any way such that i can load the model from another file in store above?
Store model attribute means you have to give the definition of Model not instance of model
Ext.define('app.model.User', {
extend: 'Ext.data.Model',
fields: ['first', 'last']
});
var store = Ext.create('Ext.data.Store',{
model: 'app.model.User'
});
Now if you want to add data to grid using model
var model = Ext.ModelManager.create({
first: 'Ed',
last: 'Spencer'
}, 'app.model.User');
store.add(model)

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.

How to store a reference to a Collection in a Model in Backbone.js?

When creating new collection (Choices) I want to set a property on it (ex: _question) which links back to the containing Model (MultipleChoiceQuestion)
This took me quite a bit of time to figure out, so in case somebody in the future has this problems...here's the code I ended up writing.
I discovered, unlike Model, Collection's initialize() function accepts 2 parameters. The first is models (which is a list of models you can initialize the collection with). The second is options (what you want). For a while my Collection started out with 1 model inside and I couldn't figure out why. Turns out I was passing my options into the models field.
THE CONTAINING MODEL:
m.MultipleChoiceQuestion = Backbone.Model.extend({
initialize: function(){
//NULL as first parameter because we don't want models
this.choices = new c.Choices(null, {
_question: this //this is referring to current question
}); //choices Collection is this
}
});
THE COLLECTION
c.Choices = Backbone.Collection.extend({
initialize: function(models, options){
this._question = options._question;
},
model: m.Choice
});
I actually found that although my 1st answer technically works, there's a plugin that makes care of storing collections in models (and creating appropriate One->Many, One->One and Many->One relationships
https://github.com/PaulUithol/Backbone-relational
Using that plugin you store the parent question as an ATTRIBUTE
m.MultipleChoiceQuestion = Backbone.RelationalModel.extend({
relations: [{
type: Backbone.HasMany,
key: 'choices', //says to store the collection in the choices attribute
relatedModel: m.Choice, //knows we are talking about the choices models
includeInJSON: true, //when we do toJSON() on the Question we want to show serialize the choices fully
reverseRelation: {
key: 'question', //in the CHOICE object there will be an attribute called question which contains a reference to the question
includeInJSON: false //when we do .toJSON on a CHOICE we don't want to show the question object (or maybe we want to show the ID property in which case we set it to "id")
}
}],
coolFunction: function () {
this.get('choices').each(function(choice){
choice.doSomethingChoicey();
});
}
});
So now if we are in the choices model we can fully reference anything in the parent question:
m.Choice = m.RelationalModel.extend({
coolFunction: function(){
this.get('question').doSomemethingQuestiony();
var question_numer = this.get('question').get('question_number');
}
});

extjs Event to update a Grid

I need a grid built in extjs designer to add data to the grid on an event.
so I should have a function that when called with receivedMsg as Args, sends the array data to be added as a new record in the grid.
I do not want it to go out and refresh a json file, not very network friendly.
I have written the server backend myself, and implemented websockets to generate the receivedMsg event.
How can I do this?
Here is where the event should go:
/*
* File: app/view/MyGridPanel.js
* Date: Sat Jan 14 2012 14:58:07 GMT-0500 (Eastern Standard Time)
*
* This file was generated by Ext Designer version 1.2.2.
* http://www.sencha.com/products/designer/
*
* This file will be generated the first time you export.
*
* You should implement event handling and custom methods in this
* class.
*/
Ext.define('MyApp.view.MyGridPanel', {
extend: 'MyApp.view.ui.MyGridPanel',
initComponent: function() {
var me = this;
me.callParent(arguments);
}
});
[
["Ace Supplies", "Emma Knauer", "555-3529"],
["Best Goods", "Joseph Kahn", "555-8797"],
["First Choice", "Matthew Willbanks", "555-4954"],
["First Choice", "Matthew Willbanks", "555-4954"]
]
If I understand the question properly, the array that you want to add as a record would first have to be converted into an instance of the same Ext.data.Model that your grid is using. Then you could call your "grid.store.insert()" method. For example, if your grid is using a model called 'Employee' like this:
// Grid data model
Ext.define('Employee', {
extend: 'Ext.data.Model',
fields: [
{name: 'name', type: 'int'},
{name: 'email', type: 'string'},
{name: 'start', type: 'date'},
{name: 'salary', type: 'int'},
{name: 'active', type: 'bool'}
]
});
You could create the model instance outside of the function with your data and just pass that as the function args, or if you can only get the data as an array (hopefully you can set the sequence), you can create the model instance inside the function itself, shown here:
// the function you wanted
addRecord: function(myRecordArray) {
// Create a model instance
var r = Ext.create('Employee', {
name: myRecordArray[0],
email: myRecordArray[1],
start: myRecordArray[2],
salary: myRecordArray[3],
active: myRecordArray[4]
});
// get the grid store and the number of records in it
var store = this.getStore();
var maxIndex = store.getCount();
// adds record to the end of the grid (args are: index, Ext.data.Model[])
store.insert(maxIndex, r)
}
You would probably have to tweak this depending on how your store is set-up but that should get it started.

backbone.js: define an initial set of models when creating a collection

I'm creating a backbone view for displaying a list of folders created by user in my webapp. but I want to have a default entry like no folder to be displayed in the list as well.
Instead of inserting the DOM inside the view, I want to just add a model to the collection which does not get synced to server but is just used to be rendered in the view.
Is there a way I can do this? I tried this an failed...
var def = {'name': 'none', 'selected': 'true'};
var coll = new app([def]);
// model here
var appitem = Backbone.Model.extend({
defaults: {
name: '',
id: '',
selected: 'false'
}
});
// collection here
app = Backbone.Collection.extend({
model: appitem,
url: '/apps'
});
You should not alter your models based on what the view needs.
If you need to display a 'no folder' entry, than it belongs in the view.
Don't complicate your life by adding data without meaning to the model layer. Keep it in the view.

Resources