I know it's more often done in the opposite way, but in my specific use case I'd need to have a Model PostsTimes with a reference to a Collection (of another Model Post). Right now I'm trying:
var Posts = Backbone.Collection.extend({
model: Post
});
var posts = new Posts(); // my collection
var PostsTimes = Backbone.Model.extend({
url: "api/times.php",
initialize: function(options){
this.posts = options.posts;
},
test: function(){
console.log(this.posts);
}
});
var poststimes = new PostsTimes({posts: posts});
But this.posts in PostsTimes always stays undefined. Is there any way I can do this without defining a global variable?
The structure of what you have is correct, so the reason it would be logging undefined is because the this in your test function is something other than the model's instance.
So your PostsTimes would become
var PostsTimes = Backbone.Model.extend({
url: "api/times.php",
initialize: function(options){
_.bindAll(this);
this.posts = options.posts;
},
test: function(){
console.log(this.posts);
}
});
var PostsTimes = Backbone.Model.extend({
url: "api/times.php",
initialize: function(options){
_.bindAll(this, 'test');
this.posts = options.posts;
},
test: function(){
console.log(this.posts);
}
});
Related
I have Backbone view that looks like this:
App.Views.HistoricalDataSelector = Backbone.View.extend({
initialize: function (options) {
this.template = JST['backbone/templates/historical_data_selector'];
this.collection = options.collection;
this.model = options.model;
this.render();
},
myCollection: function() {
return this.collection.byReportType(this.model.get('report_type')).byReportOrganizationType(this.model.get('report_organization_type'))
},
render: function () {
this.$el.html(this.template({
collection: myCollection,
model: this.model
}));
}
});
when I try to render it Backbone returns me the following error:
ReferenceError: myCollection is not defined
But when I change render method to this:
render: function () {
this.$el.html(this.template({
collection: this.collection.byReportType(this.model.get('report_type')).byReportOrganizationType(this.model.get('report_organization_type')),
model: this.model
}));
}
why he can't find this myCollection method?
You forgot the this keyword, and probably also to invoke the method:
render: function () {
this.$el.html(this.template({
collection: this.myCollection(),
//-----------^ view reference ^---- function invocation ------
model: this.model
}));
}
I'm having a hard time initializing a simple view with a collection that I'm pulling from an API. Everything I try returns an empty array when I try to return the collection from within the view.
app.models.Employee = Backbone.Model.extend({
});
app.collections.Employees = Backbone.Collection.extend({
Model: app.models.Employee,
url: "http://api.sample.com",
initialize: function(){
this.fetch();
},
parse: function(response){
console.log(response)
},
});
app.views.Container = Backbone.View.extend({
el: $('.container'),
initialize: function(){
this.collection = new app.collections.Employees();
console.log(this.collection)
var that = this;
this.collection.fetch({
success: function(){
that.render();
}
});
},
render: function(){
console.log(this.collection) //returns no models
}
});
You have to use parse correctly:
parse: function(response) {
console.log(response);
return response;
} //`,` - remove it at last item in object
There are 3 problems with your code
You are using parse incorrectly. Per the specifications
The function is passed the raw response object, and should return the
array of model attributes to be added to the collection
so yes, as #Sergey suggested
parse: function(response) {
console.log(response);
return response;
}
or better, just remove your parse function, don't override it.
You are calling your fetch function twice.
First time at this line
this.collection = new app.collections.Employees();
which eventually calls this function
initialize: function(){
this.fetch();
},
Second time is inside your initialize function in the View.
3) You break render
Again, same thing as your parse. You are supposed to
renders the view template from model data, and updates this.el with
the new HTML
Something like this
render: function() {
this.$el.html(this.template(this.model.attributes));
return this;
}
I have set up a collection for Logs. The api returns the results as JSON. I saw a previous topic where it was suggested to add the parse method on the collection. Having done so, when I execute the code I am not getting any output to the console. Nevertheless, I am new to Backbone so any insight and/or guidance would be appreciated. My understanding of collection.each may not be correct.
var Log = Backbone.Model.extend({});
var LogList = Backbone.Collection.extend({
model: Log,
url: 'api/logs',
parse: function(response) {
return response.logs;
}
});
var LogListView = Backbone.View.extend({
el: $('#logs-list'),
initialize: function() {
this.collection = new LogList();
this.collection.fetch();
this.render();
},
render: function() {
this.collection.each(function(log) {
console.log('log item.', log);
});
}
});
$(document).ready(function(){
console.log('ready.');
new LogListView();
});
Fetch is asynchronous. Rewrite your code to call render with a callback:
var LogListView = Backbone.View.extend({
el: $('#logs-list'),
initialize: function() {
var self = this;
this.collection = new LogList();
this.collection.fetch().done(function(){
self.render();
});
},
render: function() {
this.collection.each(function(log) {
console.log('log item.', log);
});
}
});
I have an application using backbone but whenever I call the fetch() method for the collection it returns undefined:
// App
(function () {
window.app = {};
app.collections = {};
app.models = {};
app.views = {};
$(function () {
app.collections.complaintTypes = new app.collections.ComplaintTypesCollection();
app.views.complaintTypesView = new app.views.ComplaintTypesView({ collection: app.collections.complaintTypes });
});
})();
// Collections
(function (collections, model) {
collections.ComplaintTypesCollection = Backbone.Collection.extend({
initialize: function () {
this.fetch();
},
model: model,
url: '/api/ComplaintTypes'
});
})(app.collections, app.models.ComplaintType);
// Models
(function (models) {
models.ComplaintType = Backbone.Model.extend({
idAttribute: 'ComplaintTypeId'
});
})(app.models);
// Views
(function (views) {
views.ComplaintTypesView = Backbone.View.extend({
initialize: function () {
this.collection.on('reset', this.render, this);
},
render: function () {
console.log(this.collection);
}
});
})(app.views);
But this doesn't return anything? If I use fiddler and go to my URL: /api/ComplaintTypes I do retrieve data back so I'm not sure what Im doing wrong here?
Deleting "model" line in the collection file worked for me.
Fetch is async. If you need to get the results, you need to pass a "success" handler, i.e.:
function myHandler(models) {
}
...
this.fetch({success: myHandler});
I think the problem is that you create the view while the collection has not been fetched yet (because of JS's asynchronous behavior). Try this way:
$(function () {
app.collections.complaintTypes = new app.collections.ComplaintTypesCollection();
app.collections.complaintTypes.fetch({success:function(){
app.views.complaintTypesView = new app.views.ComplaintTypesView({ collection: app.collections.complaintTypes });
}});
});
And remove the initialize function from your collection.
Alright, so here is my main backbone code
(function ($) {
var Job = Backbone.Model.extend({});
var JobList = Backbone.Collection.extend({
model: Job,
url: "/api/jobs?format=json"
});
var JobView = Backbone.View.extend({
el: $('#jobs'),
_templatesrc: $("#job-template").html(),
_template: {},
initialize: function () {
var self = this;
_.bindAll(this, 'render');
//create the template
this._template = Handlebars.compile(this._templatesrc);
//setup data
this.collection = new JobList();
//response function from server query
var response = function () {
console.log(arguments);
self.render();
};
var response2 = function () {
console.error(arguments);
self.render();
};
this.collection.fetch();
},
render: function () {
console.log("models", this.collection.models);
$(this.el).html(this._template(this.collection.models));
}
});
var view = new JobView();
})(jQuery);
When i do this.collection.fetch() i get nothing. When i do this.collection.fetch({ success:response, error:response2}); the following error is thrown:
Backbone.View.extend.initialize.response2 app.js:29
g.wrapError backbone-min.js:104
f.Callbacks.o jquery.min.js:2
f.Callbacks.p.fireWith jquery.min.js:2
w jquery.min.js:4
f.support.ajax.f.ajaxTransport.send.d
In chrome i can tell that it returns a JSON response though, which looks like
[{"Client":"hi",
"ReporterTime":"\/Date(-62135578800000-0500)\/",
"TimeTaken":PT0S,
"Status":"Start"}]
Any ideas on why Backbone isn't turning my JSON response into the collection?
Unless I'm mistaken PT0S is not valid JSON. Try to return it wrapped in quotes:
[{"Client":"hi",
"ReporterTime":"\/Date(-62135578800000-0500)\/",
"TimeTaken":"PT0S",
"Status":"Start"}]
I've just fixed support for TimeSpans in ServiceStack.Text's JsonSerializer.
Will be available from v3.94+ on NuGet or GitHub.