I'm using this code to fetch a model from a server:
var id = args.model.get('id');
var options = {
action: 'getSubscriber',
address: args.model.get('address'),
silent: true
};
new Subscriber({ id: id }, options).fetch({
success: function(model, response) {
console.log(response);
console.log(model);
}
});
the response object contains all the data I need whereas model stores the data not as its direct attributes but as changed object. Is it wrong?
Usually I access model attributes with help of model.get('name') call. How do I access fresh attributes in that case? Should it be model.changed.thePropertyIwantToAccess?
You can use this change event
this.model.on('change', function () {
var changedAttributes = this.model.changedAttributes();
//Process the changed attributes
}, this);
Bind this events in the initialize function of the View
Ended up with this:
var Subscriber = Backbone.Model.extend({
defaults: {
id: null,
name: null,
status: null
// ...
},
initialize: function(attributes, options) {
var _this = this;
this.options = options || {};
this.on('change', function() {
_this.set(_this.changedAttributes()['0']);
});
}
// ...
Related
How could one pass a parameter through the parse/fetch function?
I want to pass the variable VARIABLE_PARAMETER in the lower Initialize-part.
Otherwise I have to write three mostly identical Collections.
Thank you for you help.
app.js
//--------------
// Collections
//--------------
DiagnoseApp.Collections.Param1_itemS = Backbone.Collection.extend({
model: DiagnoseApp.Models.Param1_item,
url: 'TestInterface.xml',
parse: function (data) {
var parsed = [];
$(data).find(/*VARIABLE_PARAMETER*/).find('PARAMETER').each(function (index) {
var v_number = $(this).attr('Number');
var v_Desc_D = $(this).attr('Desc_D');
parsed.push({ data_type: v_data_type, number: v_number, Desc_D: v_Desc_D});
});
return parsed;
},
fetch: function (options) {
options = options || {};
options.dataType = "xml";
return Backbone.Collection.prototype.fetch.call(this, options);
}
});
This is the way I initialize the app:
//--------------
// Initialize
//--------------
var VARIABLE_PARAMETER = "OFFLINE";
var offline_Collection = new DiagnoseApp.Collections.Param1_itemS();
var offline_Collection_View = new DiagnoseApp.Views.Param1_itemS({collection: offline_Collection});
//VARIABLE_PARAMETER has to be passed here in fetch I guess ??
offline_Collection.fetch({
success: function() {
console.log("JSON file load was successful", offline_Collection);
offline_Collection_View.render();
},
error: function(){
console.log('There was some error in loading and processing the JSON file');
}
});
The fetch method accepts an option argument : http://backbonejs.org/#Collection-fetch
The parse method also accepts an option argument: http://backbonejs.org/#Collection-parse
These objects are actually the same. So you may write:
parse: function (data, options) {
var parsed = [];
$(data).find(options.variableParameter).find('PARAMETER').each(function (index) {
var v_number = $(this).attr('Number');
var v_Desc_D = $(this).attr('Desc_D');
parsed.push({ data_type: v_data_type, number: v_number, Desc_D: v_Desc_D});
});
return parsed;
},
Not sure I understand your question, but if you want to "pass a parameter" from fetch to parse, and if that parameter value doesn't change for a given collection, you could just store it in the collection. You could pass the parameter to fetch as an additional property in options:
fetch: function (options) {
options = options || {};
options.dataType = "xml";
this.variableParameter = options.variableParameter;
return Backbone.Collection.prototype.fetch.call(this, options);
},
And then simply retrieve it
parse: function (data) {
// do something useful with this.variableParameter
// ...
}
app.Model.Brand = Backbone.Model.extend({});
app.Collection.BrandCollection = Backbone.Collection.extend({
model: app.Model.Brand,
parse: function (response) {
return response.brandDTOList;
}
});
var brandcollection = new app.Collection.BrandCollection();
brandcollection.url = '/brands';
brandcollection.fetch({
success: function (collection, response, options) {
app.views.brandline = new app.View.BrandPanelView({
model: brandcollection
});
$('#tab-content').empty();
$('#tab-content').append(app.views.brandline.render());
}
});
In this view a single model is passed.
app.View.BrandItemPanelView = Backbone.View.extend({
initialize: function (options) {
this.views = {};
this.model.bind('destroy', this.remove, this);
},
events: {
'click .bra-edt': 'brandEditAction',
},
brandEditAction: function () {
this.model.get('image');
}
});
When i do this.model.get('image'); i get get is not a function.
I am not sure why i am getting such a error.
I tried to deep clone it but still no success. The values are there.
var newModel = new app.Model.Brand();
newModel = $.extend(true, {}, self.model);
newModel.get('image')
Your problem is where you are passing in your BrandCollection, instead of passing it in as a collection you are passing it in as a model.
So instead of
app.views.brandline = new app.View.BrandPanelView({
model: brandcollection
});
You probably want to do
app.views.brandline = new app.View.BrandPanelView({
collection: brandcollection
});
How are you instantiating the BrandItemPanelView?
You will have to pass in the model explicitly:
var view = new app.View.BrandItemPanelView({ model: myModel });
If myModel is in fact a Backbone model, it ought to have the get function...
view.model // should return your model
view.brandEditAction() // should run the function and get the 'image' attribute from your model
I am trying to return profile.toJSON() to an object so as to use it outside the above code. I am not understanding exactly how backbone function works, so i declare a global variable obj and trying to parse data with obj = profile.toJSON(). When i use console.log(obj) it displays successfully my data. When I put console outside the above code it returns underfined.
var obj;
var ProfileView = Backbone.View.extend(
{
el: "#profiles",
template: _.template($('#profileTemplate').html()),
render: function(eventName)
{
_.each(this.model.models, function(profile)
{
var profileTemplate = this.template(profile.toJSON());
obj = profile.toJSON();
$(this.el).html(profileTemplate);
}, this);
return this;
}
});
You're taking it by the wrong end. Precreate your model and pass it to a view. Don't try to extract something from the view rendering code, it's not meant to be used this way.
var Profile = Backbone.Model.extend({});
var ProfileCollection = Backbone.Collection.extend({
model: Profile
});
var ProfileListView = Backbone.View.extend({
...
// Everything render does is rendering
render: function() {
this.collection.each(function(model) {
this.$el.append(
this.template(model.toJSON);
);
}, this);
}
...
});
// Your profile instance is defined outside the view, making
// it de facto available to outside code
var profile = new Profile({
name: 'Fere Res',
rep: 48
});
// The profile we just created gets added to a collection
var profiles = new ProfileCollection([profile]);
// We create the profile list view and pass it the collection
var view = new ProfileListView({collection: profiles});
// When we render the view, the render() code defined above is called.
// You can easily see that all the params/variables it uses are in place
view.render();
// Rendering is done, let's check our model is still available
console.log(profile.toJSON()); // :)
I ve got this code which actually fetch data from json file:
$(function() {
var Profile = Backbone.Model.extend({
defaults: {
tstamp: "",
map:"",
tagsCloud:"",
sentiment: "",
usersCloud: "",
timeline: "",
highlights: "",
signals: ""
},
initialize: function() {
}
});
var ProfileList = Backbone.Collection.extend({
model: Profile,
url: 'data.json'
});
var ProfileView = Backbone.View.extend({
el: "#profiles",
template: _.template($('#profileTemplate').html()),
render: function(eventName) {
_.each(this.model.models, function(profile){
var profileTemplate = this.template(profile.toJSON());
//obj = profile.toJSON();
//console.log(obj.tstamp);
$(this.el).html(profileTemplate);
}, this);
return this;
}
});
var profiles = new ProfileList();
var profilesView = new ProfileView({model: profiles});
setInterval(function() {
profiles.fetch({reset: true});
}, 400); // Time in milliseconds
profiles.bind('reset', function () {
profilesView.render();
});
});
I tried to add profiles to a new collection:
var profiles1 = new ProfileList([profiles]);
var view = new ProfileView({collection: profiles1});
view.render();
console.log(profile.toJSON());
I ve got console message: Cannot read property 'models' of undefined
I'm using the get backbone method on a collection but in the same file (router),in a function works while in other function doesn't work.Below the function where doesn't works
var Models = {};
var AppRouter = Backbone.Router.extend({
routes: {
"": "home",
"user/:id":"userDetails",
"settings":"settings",//mettere id dell utente loggato
"friends":"friends",
"mailbox":"mailbox",
"landscape":"landscape",
"gestione_richieste_amic":"gestione_richieste_amic"
},
friends: function(){
console.log("friend_router");
var self=this;
Models.utenti = new Usercollection();
Models.utenti.fetch({
success: function(object) {
console.log(object);
var view=new FriendsView({model:object});
self.changePage(view);
},
error: function(amici, error) {
}
});
console.log(Models.utenti);
var cur_user=Parse.User.current().id;
console.log(Models.utenti.get(cur_user));<--undefined, don't works here
console.log(cur_user);
} ,
The reason for this the Asynchronous nature of Ajax (fetch method).
The line where you log to the console will be executed before the collection is fetched. So you see an error.
1st Option - resolving the error is moving the log to inside of the success handler
friends: function () {
console.log("friend_router");
var self = this,
Models.utenti = new Usercollection();
Models.utenti.fetch({
success: function (object) {
console.log(object);
var view = new FriendsView({
model: object
});
self.changePage(view);
console.log(Models.utenti);
var cur_user = Parse.User.current().id;
console.log(Models.utenti.get(cur_user));
console.log(cur_user);
},
error: function (amici, error) {
}
});
},
2nd Option - you might take is to bind a sync event on the collection..
initialize: function () {
this.Models.utenti = new Usercollection();
this.listenTo(this.Models.utenti, 'sync', this.logCollection);
_.bindAll(this, 'logCollection');
},
logCollection: function () {
console.log(this.Models.utenti);
var cur_user = Parse.User.current().id;
console.log(this.Models.utenti.get(cur_user));
console.log(cur_user);
},
friends: function () {
console.log("friend_router");
var self = this;
this.Models.utenti.fetch({
success: function (object) {
console.log(object);
var view = new FriendsView({
model: object
});
self.changePage(view);
},
error: function (amici, error) {
}
});
},
how do I remove remove a model in collection and make the remove event fire . I tried people.remove([{ name: "joe3" }]); but it wont work.
var Person = Backbone.Model.extend({
initialize: function () {
console.log(" person is initialized");
},
defaults: {
name: "underfined",
age:"underfined"
}
});
var People = Backbone.Collection.extend({
initialize: function () {
console.log("people collection is initialized");
this.bind('add', this.onModelAdded, this);
this.bind('remove', this.onModelRemoved, this);
},
model: Person,
onModelAdded: function(model, collection, options) {
console.log("options = ", options);
alert("added");
},
onModelRemoved: function (model, collection, options) {
console.log("options = ", options);
alert("removed");
},
});
//var person = new Person({ name: "joe1" });
var people = new People();
//people.add([{ name: "joe2" }]);
people.add([{ name: "joe1" }]);
people.add([{ name: "joe2" }]);
people.add([{ name: "joe3" }]);
people.add([{ name: "joe4" }]);
people.add([{ name: "joe5" }]);
people.remove([{ name: "joe3" }]);
console.log(people.toJSON());
For anyone else looking for a remove where, you can simply chain it with a collection.where call. like so to remove all items matching the search:
people.remove(people.where({name: "joe3"}));
see Backbone collection.where
By doing:
people.remove([{ name: "joe3" }]);
you don't remove a model, because you pass just an plain object which is not connected to people collection. Instead you could do something like this:
people.remove(people.at(2));
Or:
var model = new Person({name: "joe3"});
people.add(model);
...
people.remove(model);
will work as well.
So you need to reference actual model object from a collection;
http://jsfiddle.net/kD9Xu/
Another way is shorter a little and fires the remove event for a collection as well:
people.at(2).destroy();
// OR
people.where({name: "joe2"})[0].destroy();
Triggers a "destroy" event on the model, which will bubble up through any collections that contain it.. http://backbonejs.org/#Model-destroy
var Person = Backbone.Model.extend({
defaults: {
name: "underfined",
age:"underfined"
}
});
var People = Backbone.Collection.extend({
initialize: function () {
this.bind('remove', this.onModelRemoved, this);
},
model: Person,
onModelRemoved: function (model, collection, options) {
alert("removed");
},
getByName: function(name){
return this.filter(function(val) {
return val.get("name") === name;
})
}
});
var people = new People();
people.add(new Person({name:"joe1"}));
people.add(new Person({name:"joe2"}));
people.remove(people.getByName("joe1"));
console.info(people.toJSON());
In order to remove "[0]" you can use the following code:
people.findWhere({name: "joe2"}).destroy();