I was trying to extend backbone collections, the first way i was doing new in the declaration and in the second I declared first and then I created a new instance. Is doing the first wrong, what is the difference?
var AppointmentList = new Backbone.Collection.extend({
model: Appointment
});
and
var AppointmentList = Backbone.Collection.extend({
model: Appointment
});
var aptlist = new AppointmentList();
The first one will break
var Appointment = Backbone.Model.extend({
defaults: {
"time": "0000",
"note": "This is an appointment"
}
});
var AppointmentList = new Backbone.Collection.extend({
model: Appointment
});
var aptlist = new AppointmentList();
In in Backbone.js we have
var extend = function(protoProps, staticProps) {
var parent = this;
var child;
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function(){ return parent.apply(this, arguments); };
}
_.extend(child, parent, staticProps);
var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;
if (protoProps) _.extend(child.prototype, protoProps);
child.__super__ = parent.prototype;
return child;
};
If you instantiate Backbone.Collection.extend with the new operator, then the var parent = this will refer to the extend object, but if you don't use new then var parent = this will refer to Backbone.Collection and since you can only call .apply on functions, the code will break here:
child = function(){ return parent.apply(this, arguments); };
parent will be an object. Backbone.Collection is a function
Related
var Wine = Backbone.Model.extend({
winename: "Charles Shaw"
})
var Wines = Backbone.Collection.extend({
Model: Wine
})
var divElement = Backbone.View.extend({
initialize: function () {
this.render();
},
tagName: "ul",
render: function () {
$("#div1").empty();
$("#div1").append("<ul id='ulList'></ul>"),
wines.each(function (model) {
$("#ulList").append("<li>" + model.winename + "</li>");
});
return this;
}
});
var wine1 = new Wine();
wine1.winename = "wine1";
var wines = new Wines();
wines.add(wine1);
var wine2 = new Wine();
wine2.winename = "wine2";
wines.add(wine2);
function changewinename(model, winename) {
this.winename = winename;
}
var d = new divElement(wines);
wines.on("add", addwinename);
wines.on("remove", removewinename);
function addwinename(model, winename) {
d.initialize();
}
function removewinename(model, winename) {
d.initialize();
}
function AddWine() {
var winename = $("#wineName").val();
var wineFromUI = new Wine();
wineFromUI.winename = winename;
wines.add(wineFromUI);
$("#wineName").val("");
}
function changewinename(model, winename) {
this.winename = winename;
}
function RemoveWine() {
var wineValue = $("#wineName").val();
var wine1 = new Wine();
wine1.on({ "change:winename": changewinename });
wine1.set({ winename: wineValue });
alert(wine1.winename);
wines.remove(wine1);
$("#wineName").val("");
}
Collection remove for a model isn't working. Add works fine.
you need to add a function inside your collection like this:
var Wines = Backbone.Collection.extend({
Model: Wine,
removeElement: function(elements, options) {
return this.remove(elements, options);
}
})
and call it like this in your view:
wines.removeElement(wine1);
When I render this view
var MyView = Backbone.View.extend({
/* el : '.myview', used when rendered on router request */
render : function () {
var data = new Data(); /* a collection from ajax request */
var that = this;
data.fetch({
success : function (bla, data) {
var template = _.template( $('#temp').html(), {data: data.players} );
that.$el.html(template);
}
});
}
});
on router request, it works:
var Router = Backbone.Router.extend({
routes : {
'bla' : 'bla'
}
});
var myView = new MyView();
var router = new Router();
router.on('route:bla', function () {
myView.render();
});
But when I want it simply to load with the page, it doesn't:
var myView = new MyView({ el: $(".myview") });
Because in the last line you posted, you missing call to render function.
var myView = new MyView({ el: $(".myview") });
myView.render();
Besides of that, I see the workflow of initialization a bit wiered. Namely, requesting the data inside .render() function, that violates view single responsibility. Something, that I do in my applications.
var Router = Backbone.Router.extend({
routes : {
'bla' : 'bla'
},
bla: function () {
app.BlaApp();
}
});
app.BlaApp = function () {
var collection = new Collection();
collection.fetch({
success: function (collection) {
var view = new app.BlaView({model: collection});
view.render();
}
})
}
app.BlaView = Backbone.View.extend({
render: function () {
var template = // render template based on this.model;
this.$el.html(template);
return this;
}
});
I am developing a Backbone web application and I want to know that how can post data from the view
This is my Model:
App.Models.edit = Backbone.Model.extend({
defaults : {
id : undefined,
fname : undefined,
lname : undefined,
phone : undefined,
address : undefined,
email : undefined,
url: undefined,
},
initialize: function(){
this.set({url : '../api/getOne/' + App.CurrentID });
},
getAttrs: function(attr){
return this.get(attr);
}
});
And this is my view:
App.Views.edit = Backbone.View.extend({
el: $("#modal"),
initialize: function(){
App.TplNames.edit = $('body');
App.Tpls.edit('edit');
this.model.bind("reset", this.render, this);
this.render();
},
events: {
'click .btnSave': 'saveDetails',
},
saveDetails: function(){
this.model.save();
//console.log(this.model);
},
render: function(){
var elem = '';
$.each(this.model.models, function(i, k){
var template = _.template( $('#tpl_edit').html(), k.toJSON() );
elem += template;
});
$(this.el).html(elem);
$("#myModal").modal('show');
$("#myModal").on('hidden', function(){
//alert(123);
document.location.href = App.Url + '#view';
});
var attrs = "";
$.each(this.model.models, function(i, k){
attrs = k.toJSON();
});
$("#fname").val(attrs.fname);
$("#lname").val(attrs.lname);
$("#Email").val(attrs.email);
$("#Phone").val(attrs.phone);
$("#Address").val(attrs.address);
//console.log(attrs);
}
});
And it is my Router
App.Router = Backbone.Router.extend({
routes: {
"" : "def",
"home" : "def",
"view" : "getAll",
"edit/:id" : "edit",
"add" : "addContact",
},
def: function(){
this.mainModel = new App.Collections.Main();
this.mainView = new App.Views.Main({model: this.mainModel});
//this.mainModel.fetch();
},
edit: function(id){
App.CurrentID = id;
var contactCollObj = new App.Collections.edit();
viewObj = new App.Views.edit({model: contactCollObj});
contactCollObj.fetch();
viewObj.render();
//console.log(contactCollObj);
},
getAll: function(){
//alert(123);
var collObj = new App.Collections.View();
var viewObj = new App.Views.View({model: collObj});
collObj.fetch();
},
addContact: function(){
//var model = new App.Collections.AddContact();
model = new App.Models.AddContact();
var view = new App.Views.AddContact({model: model});
//view.render();
}
});
var app = new App.Router();
Backbone.history.start();
And when I want to save the model, It generates an error:
this.model.save is not a function
Every thing is okay except the above...
In your router you pass collection to App.Collections.edit view as model:
var contactCollObj = new App.Collections.edit();
viewObj = new App.Views.edit({model: contactCollObj});
That is why you cannot call save(). save() is only available for a model not a collection.
You probably want to initialize view with collection
viewObj = new App.Views.edit({collection: contactCollObj});
And then also modify some of your view code accordingly.
I've fetch() a model by a server and I want to render the results of fetch() with a view.
The results of fetch() is an array of objects (var risultati) and I want render this var risultati. I've tried but nothing works.
var AppRouter = Backbone.Router.extend({
routes: {
"": "list",
},
initialize: function () {},
list: function () {
var utente = new Person();
var risultati;
utente.fetch({
success: function (data) {
var ris = data.attributes;
var risultati = ris.results;
console.log(risultati); /* risultati contains array of object to render*/
}
});
this.page = new UserListView({
model: this.utente
});
$('body').append(this.page.$el);
}
});
You may be having problems because your call to render the view is occurring separate from your utente.fetch() call.
Since .fetch() is asynchronous, your view code will be executed before .fetch() has finished. You should add the view creation/rendering as part of the success function, or you should bind the change event that occurs when the model is updated to fire off a new function that contains your view creation.
You should separate your MVC logic... don't attach objects (collections I think) to a router route handler.
Assuming that you are trying to render a collection of person models, I suggest you use a model and view for the person and a collection and a view for handling the "array of objects" :
var Person = Backbone.Model.extend({
initialize : function(){
// initialize the view
this.view = new PersonView({model : this});
}
}),
PersonView = Backbonke.View.extend({
render : function(){
// render your person
}
}),
UserList = Backbone.Collection.extend({
model : Person,
initialize : function(){
this.view = new UserListView({
collection : this
});
},
update : function(){
var self = this;
this.fetch({
success: function (data) {
var ris = data.attributes;
var risultati = ris.results;
console.log(risultati); /* risultati contains array of object to render*/ self.view.render();
}
});
}
}),
UserListView = Backbone.View.extend({
render : function(){
this.collection.each(function(el,i){
el.view.render();
});
}
});
and then use it as :
var page = new UserList();
var AppRouter = Backbone.Router.extend({
routes: {
"": "list",
},
initialize: function () {},
list: function () {
page.update();
}
});
Hope this helps!
I have the following backbone.js code and i have a problem in that event before i fetch the "add" event is triggered from the collections. Adding this.field.add(list_fields); in the success: fetch has resulted in an error. How do i make sure the model is fetched then the add event is run after that
$(function() {
$(".chzn-select").chosen();
/*********************************Models*************************************************/
var Table = Backbone.Model.extend({
urlRoot : '/campusfeed/index.php/welcome/generate'
});
var Field = Backbone.Model.extend({
urlRoot: '/campusfeed/index.php/welcome/generate'
});
/**************************Collections*************************************************/
Tables = Backbone.Collection.extend({
//This is our Friends collection and holds our Friend models
initialize : function(models, options) {
this.bind("add", options.view.addFriendLi);
//Listen for new additions to the collection and call a view function if so
}
});
var Fields = Backbone.Collection.extend({
model:Field,
url:'http://localhost/campusfeed/index.php/welcome/generateFields',
initialize : function(models, options) {
this.bind("add", options.view.getFields);
}
});
/************************************Views**************************************************/
var m="shit";
var app = Backbone.View.extend({
el:'body',
initialize:function(model,options){
//Create collections in here
this.table = new Tables(null,{
view : this
});
this.field = new Fields(null,{
view : this
});
},
events : {
"click #choose" : "generate"
},
generate:function(){
var table = ( this.$("#table option:selected").text());
var dbname = ( this.$("#database").text());
var list_fields = new Field();
list_fields.urlRoot = list_fields.urlRoot+"/"+dbname+"/"+table;
list_fields.fetch({
success:function(){
console.log(JSON.stringify(list_fields));
}
});
this.field.add(list_fields);
},
getFields:function(model){
console.log(JSON.stringify(model));
}
});
var apprun = new app;
/* var data = new Fields();
data.url=data.url+"/some/data";
alert(data.url);
data.fetch();
var staff = new Table();
staff.fetch();
var field = new Field();*/
});
the problem is the context of "this". the success callback function has "this" set to the list_fields. you can work around this with a "self" or "that" variable:
generate:function(){
var table = ( this.$("#table option:selected").text());
var dbname = ( this.$("#database").text());
var list_fields = new Field();
list_fields.urlRoot = list_fields.urlRoot+"/"+dbname+"/"+table;
var that = this;
list_fields.fetch({
success:function(){
console.log(JSON.stringify(list_fields));
that.field.add(list_fields);
}
});
},
as a side note - your collections should never have a reference to a view. instead, your view should reference the collection and bind to the collection event
var Fields = Backbone.Collection.extend({
model:Field,
url:'http://localhost/campusfeed/index.php/welcome/generateFields',
});
var app = Backbone.View.extend({
initialize:function(model,options){
//Create collections in here
this.field = new Fields();
this.field.bind("add", this.getFields, this);
},
getFields: function(){ ... }
});