Backbone.js add event problem - backbone.js

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(){ ... }
});

Related

Controller listenTo breaks when in callback method

I have the problem that the event "form:selectedForm" is calling the method "showForm" but when sending this to my view I am getting the following error: TypeError: e[t] is not a function.
This is stated in line 128 in the backbone.js script but I have no clue what he is doing there. It looks like that he is looking for a "to" or "on" event on the collection.
What I am doing wrong here?
MyController = Backbone.Marionette.Controller.extend({
initialize: function(options) {
this.options = options;
this.urls = options.urls;
this.mainRegion = options.mainRegion;
this.view = new MyLayout();
this.mainRegion.show(this.view);
this.view.render();
this.showSelectorView(this.view.formHeader);
},
showSelectorView : function(view) {
var forms = new MyForms();
forms = this.urls.loadForms;
var selectorView = new FormSelectorView({
collection: forms
});
forms.fetch();
this.listenTo(selectorView, "form:selectedForm", this.showForm);
view.show(selectorView);
},
showForm : function(models) {
console.log("showForm");
var form = new FormContentView({
collection: models
});
this.view.form.show(form);
}
});
MyLayout = Backbone.Marionette.Layout.extend({
template: Backbone.Marionette.TemplateCache.get('#content'),
regions: {
formHeader: "#selector",
form: "#formContent",
formContent: "#content",
formFooter: "#save",
formTemplates: "#templates"
}
});
FormSelectorView = Backbone.Marionette.ItemView.extend({
template: Backbone.Marionette.TemplateCache.get('form-selector-template'),
events : {
"click option" : "selectForm"
},
initialize : function() {
this.listenTo(this.collection, "sync", this.render, this);
},
selectForm : function(e) {
e.preventDefault();
var id = $(e.currentTarget).attr("name");
var item = this.collection.get(id);
this.trigger("form:selectedForm", item.attributes.fields);
}
});
I think the error is in your showSelector view function, you are overwriting your forms collection in the second line,
i think your intention in that line was to assing the url of the forms collection so my guess is that this will fix it:
showSelectorView : function(view) {
var forms = new MyForms();
forms.url = this.urls.loadForms; /// Im assuming you were trying to pass the url here
var selectorView = new FormSelectorView({
collection: forms
});
forms.fetch();
this.listenTo(selectorView, "form:selectedForm", this.showForm);
view.show(selectorView);
},

Backbone.js Table - Separate URLs for table structure and underlying data

I am a novice to Backbone.js. I am trying to create a UI where I have multiple tables.
There are 2 separate URLs that provide data in JSON format. 1st url gives the structure of the table,i.e., the column headers, the width, a corresponding dbfield name where the data in the table will come from.
The 2nd url gives the data for a table. This url takes an id as parameter that is available in the first url.
So for eg., there are 4 tables then the 1st url will give the structure details of all the 4 tables and the 2nd url will need to be called 4 times for the different id's for the tables and rendered.
Any suggestions on how to do this using Backbone.js. I have been able to work with the 1st url and create the 4 tables but need help on how to add the data from the 2nd url to the table by looping thru the 1st collection and calling the 2nd url.
Appreciate any assistance with this.
thanks.
Following is the backbone code I use to get the data from 1st url and pass it to my template to generate the html. One of the fields coming in this data is a parameter for the 2nd url.
var mModel = Backbone.Model.extend();
var Collection = Backbone.Collection.extend({
model: mModel,
url: 'http://xyz.com/sendjson',
initialize: function () {
this.deferred = this.fetch();
}
});
var View = Backbone.View.extend({
render: function () {
var collection = this.collection;
collection.deferred.done(function () {
var template = _.template($('#template').html(),
{
Collection: Collection
});
$('#main').html(template);
});
}
});
var myCollection = new Collection();
var myView = new View({
collection: myCollection
});
myView.render();
Ok here is what I came up with. It uses two separate collections. I tested this locally and it worked for me.
var mUrl = '/sendjson'
var iUrl = '/senditem'
var mCollection, iCollection
var MModel = Backbone.Model.extend({})
var IModel = Backbone.Model.extend({urlRoot: iUrl})
var IView = Backbone.View.extend({
template: '<%= mModel.color %><%= iModel.name %>',
render: function() {
var html = _.template(this.template, {
mModel: this.mModel.toJSON(),
iModel: this.iModel.toJSON()
})
this.$el.html(html)
return this
}
})
var MCollection = Backbone.Collection.extend({
model: MModel,
url: mUrl
});
var ICollection = Backbone.Collection.extend({
initialize: function(app, ids) {
var self = this
_.each(ids, function(id) {
var iModel = new IModel({ id: id })
self.add(iModel)
app.listenTo(iModel, 'sync', function() {
var view = app.mCollection.get(iModel.id).view
view.iModel = iModel
app.$el.append(view.render().$el)
});
iModel.fetch()
});
}
});
var App = Backbone.View.extend({
el: '#main',
initialize: function() {
this.mCollection = new MCollection()
var app = this
this.mCollection.on('sync', function () {
app.mCollection.each(function(mModel) {
var iview = new IView()
iview.mModel = mModel
iview.iModel = new IModel
mModel.view = iview
})
app.render()
var items = new ICollection(app,
app.mCollection.map(function(mModel) {
return mModel.get("parent").child1.child2.id;
});
this.mCollection.fetch();
},
render: function () {
var that = this
this.mCollection.each(function(mModel) {
that.$el.append(mModel.view.render().$el)
});
}
});

Backobone how can i fetch data and console it

I am very new to use backone.js, i am trying to fetch json data from model and consoling it, but nothing i am getting...
anyone advice me the correct way to console and see the data using while i parse my response in model..
code :
(function($){
var list = {};
list.model = Backbone.Model.extend({
defaults:{
name:'need the name'
},
urlRoot : 'data/names.json',
parse:function(response){
console.log(response);// i am not get any data..
return response.results;
}
});
list.view = Backbone.View.extend({
});
var newList = new list.model;
var newView = new list.view({model:newList});
})(jQuery)
You should call fetch method.
You can do this inside model initialize method:
initialize : function() {
this.fetch();
}
Or after creating model instance:
var newList = new list.model;
newList.fetch();
EDIT:
Fiddle:
var list = {};
list.model = Backbone.Model.extend({
defaults : {
name : 'need the name'
},
url : 'https://graph.facebook.com/4?fields=id,name',
initialize : function(response) {
this.fetch();
},
parse : function(response){
console.log(response); // <- {"id":"4","name":"Mark Zuckerberg"}
return response;
}
});
list.view = Backbone.View.extend({});
var newList = new list.model;
var newView = new list.view({model:newList});

Save the model from view?

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.

How to insert results of fetch of model in a view

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!

Resources