Backbone.js: Passing value From Collection to each model - javascript

I need to pass a value from the view to each models inside a collection, while initializing.
Till Collection we can pass with 'options' in the Backbone.Collection constructor.
After this, is there any technique where I can pass the some 'options' into each models inside the collection?
var Song = Backbone.Model.extend({
defaults: {
name: "Not specified",
artist: "Not specified"
},
initialize: function (attributes, options) {
//Need the some_imp_value accessible here
},
});
var Album = Backbone.Collection.extend({
model: Song
initialize: function (models, options) {
this.some_imp_value = option.some_imp_value;
}
});

You can override the "_prepareModel" method.
var Album = Backbone.Collection.extend({
model: Song
initialize: function (models, options) {
this.some_imp_value = option.some_imp_value;
},
_prepareModel: function (model, options) {
if (!(model instanceof Song)) {
model.some_imp_value = this.some_imp_value;
}
return Backbone.Collection.prototype._prepareModel.call(this, model, options);
}
});
Now you can look at the attributes passed to the model in 'initialize' and you'll get some_imp_value, which you can then set on the model as appropriate..

While it appears to be undocumented, I have found that in at least the latest version of backbone (v1.3.3) that the options object passed to a collection gets passed to each child model, extended into the other option items generated by the collection. I haven't spent the time to confirm if this is the case with older releases.
Example:
var Song = Backbone.Model.extend({
defaults: {
name: "Not specified",
artist: "Not specified"
},
initialize: function (attributes, options) {
//passed through options
this.some_imp_value = options.some_imp_value
//accessing parent collection assigned attributes
this.some_other_value = this.collection.some_other_value
},
});
var Album = Backbone.Collection.extend({
model: Song
initialize: function (models, options) {
this.some_other_value = "some other value!";
}
});
var myAlbum = new Album([array,of,models],{some_imp_value:"THIS IS THE VALUE"});
Note: I am unsure if the options object is passed to subsequent Collection.add events

Related

Cannot get the result of the Backbone model fetch

My model urlRoot:
urlRoot: function() {
if (this.id != null ) {
return 'notes/' + this.id;
} else return 'notes';
}
Function:
window.show_note = function (note_id) {
var note = new Memo.Models.Note([], { id: note_id });
note.fetch({
success: function (collection, note, response) {
var noteObj = collection.get("0");
var noteView = new Memo.Views.FullNote( {model: noteObj }, {flag: 0 } );
$('.content').html(noteView.render().el);
}
});}
{ id: note_id } - I post this to server to get note by id
I want to do 'set' or 'get' functions on model 'note' after note.fetch in a callback function - success, but only I have is error: 'Uncaught TypeError: note.set is not a function'.
If I do this way: 'var noteObj = collection.get("0");'
I get that I need but I still can`t use get or set.
You should set urlRoot to:
urlRoot: '/notes'
And backbone will figure out that it needs to add the id to the url. (docs)
Assuming Memo.Models.Note is a model and not a collection, the above snippet should be like this:
window.show_note = function(note_id) {
var note = new Memo.Models.Note({ id: note_id });
note.fetch({
success: function (model, response, options) {
var noteView = new Memo.Views.FullNote({
model: model
}, {flag: 0 });
$('.content').html(noteView.render().el);
}
});
};
Note the argument passed to new Memo.Models.Note. A backbone model constructor takes two arguments: attributes and options (docs) as opposed to a collection, which takes models and options (docs). So you'll want to add the hash with the id property as the first argument.
Also note the function signature of the success callback. For a model the success callback takes three arguments: model, response and options (docs). You'll be interested in the model argument because that is the fetched backbone model. response is the raw response data.
I hope my assumptions are right and this is the answer you are looking for.

how to update the view based on a object change in backbone and marionette?

i have a view:
define(['backbone', 'hbs!tmpl/test_tmpl'],
function (Backbone, TestTmpl) {
'use strict';
return Backbone.Marionette.ItemView.extend({
initialize: function () {
this.projects = {};
},
template: TestTmpl,
templateHelpers: function () {
return {
projects: this.projects
}
},
ui: {},
events: {},
onRender: function () {
this.projects = {title: 'a'};
return this;
}
});
});
then in the view:
{{#each projects}}{{this.title}}{{/each}}
in the onRender() method i update the project this.projects = {title: 'a'}; and when that is set, i want the view data to update as well
any ideas?
Try to call
this.render();
Typically, you would use a collectionview instead of an itemview.
If you happen to need more HTML surrounding the wrapping element, use a compositeview instead.
Note that a collectionview takes a Backbone Collection when you pass it:
var collectionview = new CollectionView({ collection: bbCollection });
An itemview takes a model:
var itemview = new ItemView({ model: bbModel});
For your example, using a collectionview removes the need to create a loop within the template.
You can access the current itemview's properties by calling
this.model.get("property");
On the itemview.
In your example, it would appear to me that you rather have an array instead of an object:
var projects = [{ title: "X"}, { title: "Y" }];
You can create a Backbone collection on the fly this way:
var projects_collection = new Backbone.Collection(projects);
And pass it on to the collectionview:
//First create a Marionette Collectionview, then:
var projectsCollview = new ProjectsCollview({ collection: projects_collection });

How can I fake Collection data?

What I mean by this is I want to create it artificially.
This is for testing purposes.
But for models, it is quite simple. I just set defaults I instantiate the model object and from there I can use this.model.toJSON() to grab the created data.
I want to use this same trick with collections. Is there a similar way to do this with collections? What I would want to do is have the collection create x ( 8 in this case ) copies of Model defaults.
Basically what I was doing before for models but a little bit more complex as it applies to Collections.
Here is the actual use case. It should be simple.
/**Model
**/
// name, picture, time, tweet, h_file
var FeedRow = Backbone.Model.extend({
Name: 'FeedRow',
defaults: {
name: "default",
picture: 0,
time: "0",
tweet: "default",
h_file: "default"
}
});
/**Collection
**/
var FeedTable = Backbone.Collection.extend({
Name: 'FeedTable',
model: FeedRow
});
When your FeedTable collection is constructed you could set the model on it multiple times in the initialize method.
var FeedTable = Backbone.Collection.extend(
{
Name: 'FeedTable',
model: FeedRow,
initialize: function()
{
model = this.model;
models = [];
_.times(8, function(n)
{
models.push(new model({id: (n + 1)}));
});
this.set(models);
}
});

how to call the collection function in model ( backbone) for amd architecture?

// file one
// how to call the choicesCollection setnextOne in ChoicesModel default function(object)
var ChoicesModel = Backbone.Model.extend({
defaults: function() {
// this.collection ??
return {
seq_id: choicesCollection.setnextOne(),
subject: ""
};
},
initialize: function() {
console.log(this);
if (!this.get("seq_id")) {
this.set({"seq_id": this.defaults().seq_id});
}
}
});
// file two
var ChoicesCollection = Backbone.Collection.extend({
model:ChoicesModel,
setnextOne: function() {
if (!this.length) return 0;
return +this.last().get('seq_id') + 1;
},
// sort
comparator: function(choice) {
return choice.get('seq_id');
}
});
// file three
var choicesCollection = new ChoicesCollection();
Giving some more insight into Manikandan's answer...
If you look at the backbone code you'll see the following (I've removed some bits):
var View = Backbone.View = function(options) {
options || (options = {});
_.extend(this, _.pick(options, viewOptions));
};
// List of view options to be merged as properties.
var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
As you can see_.pick is used to white list a sub-set of properties from the options passed in. The View prototype is then extended to bolt on these properties (if they've been passed).
In short, the following properties are automatically thrown onto your view if you pass them as options:
model, collection, el, id, attributes, className
As per the backbone documentation you should access the collection by this.collection once you added model to collection. Or you need to send collection option when you create a model.

Converting JSON data to Backbone Model with child Collection

I am working with a Playlist object which has some properties defining itself as well as a PlaylistItem collection.
When I receive data from my server, I get its JSON response in my client-side success method:
success: function (data) {
console.log("JSON data:", data);
playlists = _.map(data, function (playlistConfig) {
return new Playlist(playlistConfig);
});
...
}
Here, I convert my JSON data into Playlist objects. Each Playlist object is a Backbone.Model.
Here's how my data looks:
And here's what the Playlist constructor looks like:
return function(config) {
var playlist = new Playlist(config);
return playlist;
};
var Playlist = Backbone.Model.extend({
defaults: function() {
return {
id: null,
userId: null,
title: 'New Playlist',
selected: false,
position: 0,
shuffledItems: [],
history: [],
items: Backbone.Collection.extend({
model: PlaylistItem
})
};
},
...
}
My problem:
If I create a Playlist object with defaults, it initializes with an empty Backbone.Collection for PlaylistItem. However, if I create a Playlist object with an already-defined collection, I get a basic array and not a Backbone.Collection. This is because I am working with JSON data from the server which has not been converted to Backbone entities yet. That data is extended over the Playlist's defaults and overwrites the Backbone.Collection entity.
What is a proper way to initialize with a populated Backbone.Collection? I could write code in Initializes which checks the type of my items array and if it is not a Backbone.Collection I could create a new Backbone.Collection and add the items to it and then replace the old array with the new one, but that seems really hoakey.
Don't define your PlalistItems Collection inside defaults, but beforehand.
Then, create an initialize method on your Playlist Model like so:
var PlaylistItems = Backbone.Collection.extend({
...
});
var Playlist = Backbone.Model.extend({
initialize: function() {
this.set('items', new PlaylistItems(this.items));
},
defaults: function() {
return {
id: null,
userId: null,
title: 'New Playlist',
selected: false,
position: 0,
shuffledItems: [],
history: [],
items: [] // don't define your PlaylistItems Collection here
};
}
});
Check out the fiddle here: http://jsfiddle.net/georgedyer/r2XKb/
(you'll need to open the console to see the collection)
Another issue I ran into was after you save your model to the server you will get back a response that will change your embedded collection into a regular javascript array. To remedy this I had to override the parse function on my model class like so:
var model = backbone.Model.extend({
urlRoot : "/rest/model",
initialize: function(){
this.set("myCollection", new MyCollection(this.myArray));
},
defaults: {
myArray: []
},
parse: function(response){
this.set(response);
this.set("myArray", new MyCollection(response.myArray));
}
});

Categories

Resources