This question has been asked at length yet I can't seem to get any of the examples to fit my code. My model and collection populate and I get output from the console, but can;t seem to get the AppView.render to do anything other then print 'rendering view...'
var Foodtruck = Backbone.Model.extend({
defaults: {
'name': '',
'twitter': '',
'categories': [],
'coordinates': {
'latitude': 0,
'longitude': 0
}
}
});
var FoodTruckCollection = Backbone.Collection.extend({
model: Foodtruck,
url: 'http://api.mobilefeast.info/foodtrucks',
initialize: function(){
this.bind("render", function( model ){
alert("hey");
view.render( model );
})
},
parse: function(response) {
return response;
},
getData: function(){
var that = this;
that.fetch(
{
success: function () {
console.log('Data is fetched');
},
error: function() {
console.log('Failed to fetch!');
}
});
}
});
var AppView = Backbone.View.extend({
el:$('#container'),
initialize: function(){
console.log('initialize AppView');
this.foodtrucks = new FoodTruckCollection();
this.foodtrucks.getData();
},
render: function(){
console.log('rendering view...');
this.foodtrucks.each(function(model){
console.log(JSON.stringify(model));
});
}
});
new AppView().render();
tried this question: fetch after render
but no luck
Update
var AppView = Backbone.View.extend({
el:$('#container'),
initialize: function(){
console.log('Initialize');
this.foodtrucks = new FoodTruckCollection();
this.foodtrucks.fetch(
{
success: function () {
console.log('Data is fetched');
},
error: function() {
console.log('Failed to fetch!');
}
});
this.listenTo(this.foodtrucks, 'sync', this.render);
},
render: function(){
console.log('Rendering');
this.foodtrucks.each(function(model){
console.log(model.toJSON().name);
});
}
});
Related
Total newbie to Backbone so apologize if this is a simple question.
I am have successfully loaded a collection and rendered the view. However I have a dropdown with A tags that I would like to use the filter the data displayed. I'm trying to set an event listener in my VIEW and then trigger a function within the view to filter the results and re-render the view.
Here's my code:
IBA.NewsModel = Backbone.Model.extend({});
IBA.NewsCollection = Backbone.Collection.extend({
model: IBA.NewsModel,
url: "/news/api"
});
IBA.NewsView = Backbone.View.extend({
el: '#main',
template: _.template($("#news-article").html()),
events: {
"change .dropdown-item": "filterNews"
},
initialize: function () {
this.collection = new IBA.NewsCollection();
this.listenTo(this.collection, 'reset', this.render);
this.collection.fetch({
success: function() {
console.log("JSON file load was successful");
view.render();
},
error: function(){
console.log('There was some error in loading and processing the JSON file');
}
});
},
render: function () {
this.$el.html(this.template({
articles: this.collection.toJSON()
})
);
return this;
},
filterNews: function (e){
e.preventDefault();
var items = this.collection.where({cat_name: "interviews"});
console.log(items);
this.$el.html(this.template({articles: this.items.toJSON()}));
}
});
var view = new IBA.NewsView();
Easiest way to do it would be to reset the actual collection with the filtered results:
IBA.NewsModel = Backbone.Model.extend({});
IBA.NewsCollection = Backbone.Collection.extend({
model: IBA.NewsModel,
url: "/news/api"
});
IBA.NewsView = Backbone.View.extend({
el: '#main',
template: _.template($("#news-article").html()),
events: {
"change .dropdown-item": "filterNews"
},
initialize: function() {
this.collection = new IBA.NewsCollection();
this.listenTo(this.collection, 'reset', this.render);
this.fetchNews();
},
fetchNews: function() {
var view = this;
this.collection.fetch({
success: function() {
console.log("JSON file load was successful");
view.render();
},
error: function() {
console.log('There was some error in loading and processing the JSON file');
}
});
},
render: function() {
this.$el.html(this.template({
articles: this.collection.toJSON()
}));
return this;
},
filterNews: function(e) {
e.preventDefault();
this.collection.reset(this.collection.where({
cat_name: "interviews"
}));
}
});
var view = new IBA.NewsView();
When you want to go back to original data, fetch it again using the fetchNews() method.
You also had a syntax error that view was not defined in your initialize
I still strugling with memory leak in my app. I wannted to do it without huge changes in code.
var ItemsView = Backbone.View.extend({
id:'products', // If I change it to el: document.getElementById('products') and without passing views into items object, my views are properly rendered but with memory leak
events: { },
initialize: function() {
_.bindAll(this);
this.listenTo(this.collection, 'reset', this.reset);
this.listenTo(this.collection, 'add', this.addItem);
this.listenTo(this.collection, 'change', this.changeItem);
this.listenTo(this.collection, 'destroy', this.delItem);
this.items = [];
},
reset: function(){ console.log("reset");
this.el.innerHTML = null;
this.render();
},
render: function(){
for(var i=0; i < this.collection.length; i++){
this.renderItem(this.collection.models[i]);
}
},
renderItem: function( model ){
var itemView = new ItemView({ model: model });
itemView.render();
this.items.push(itemView);
jBone(this.el).append(itemView.el);
},
addItem: function(){ console.log("addItem");
this.renderItem();
},
changeItem: function(){ console.log("changeItem"); },
delItem: function(){ console.log("delItem"); },
remove: function() {
_.invoke(this.items, 'remove');
this.items = [];
Backbone.View.prototype.remove.call(this);
}
});
return ItemsView;
This is my Itemsview it is executed when user hit orderview, there is created ItemView for every model in collection:
var ItemView = Backbone.View.extend({
tagName: "li",
className: "productcc",
initialize: function () {
_.bindAll(this, 'addItem', 'removeItem', 'updateItem');
this.listenTo(this.model, 'remove', this.removeItem);
this.listenTo(this.model, 'change', this.updateItem);
},
events: {},
render: function () {
var model = this.model.toJSON();
this.el.innerHTML += '<div class="tabody"><h4 class="tablename">'+model.title+'<h4>'+model.status+'</div>';
return this;
},
addItem: function(){
this.collection.create({"table_no":"demo"});
},
changeItem: function(e){
e.preventDefault();
this.model.save({ table_no: 'demo' });
},
updateItem: function(newstuff){
console.log("updateItem");
console.log(this.el);
},
delItem: function(){
this.model.destroy({ silent: true });
},
removeItem: function(model){
console.log("removeItem");
console.log(model);
var self = this;
self.el.remove();
}
});
return ItemView;
MY ROUTER:
var AppRouter = Backbone.Router.extend({
routes: {
'' : 'home',
'home' : 'home',
'customer/:customer_id': 'showItems'
}
});
var initialize = function(options) {
window.app_router = new AppRouter;
window.socket = io.connect('www.example.com');
this.socketOrdersCollection = new SocketOrdersCollection();
this.ordersView = new OrdersView({ collection: this.socketOrdersCollection });
this.socketOrdersCollection.fetch({ reset: true });
app_router.on('route:home', function() { });
app_router.on('route:showItems', function(customer_id) {
if (this.itemsView) {
this.itemsView.remove();
}
this.socketItemsCollection = new SocketItemsCollection();
this.socketItemsCollection.fetch({ data: { id: customer_id}, reset: true });
this.itemsView = new ItemsView({
collection: this.socketItemsCollection,
model: { tableName: customer_id }
});
});
Backbone.history.start();
};
I have to remove also ItemsView after click to another order...
Thanks for any opinion.
Ok. Let me take a stab at what you're attempting here.
var ItemsView = Backbone.View.extend({
el: document.getElementById('products'),
events: { },
initialize: function() {
// everything you had before
this.items = [];
},
// etc.
renderItem: function( model ){
var itemView = new ItemView({ model: model });
itemView.render();
this.items.push(itemView);
jBone(this.el).append(itemView.el);
},
// etc.
// we're overloading the view's remove method, so we clean up our subviews
remove: function() {
_.invoke(this.items, 'remove');
this.items = [];
Backbone.View.prototype.remove.call(this);
}
});
return ItemsView;
And then in the router:
var initialize = function(options) {
// etc.
app_router.on('route:home', function() { });
app_router.on('route:showItems', function(customer_id) {
if (this.itemsView) {
this.itemsView.remove();
}
// everything else the same
});
Backbone.history.start();
};
So now, your ItemsView will clean up any child items it has, and when you change customers, you'll clean up any ItemsView you have open before generating a new one.
EDIT
I see what you're having a problem with now.
In your route handler, you're going to need to do something along these lines:
app_router.on('route:showItems', function(customer_id) {
// everything you already have
jBone(document.getElementById('container')).append(this.itemsView);
});
I'm not getting any attributes or options in model. I need to pass a route number to it in order to build a url. anyone see what im missing or how I should be doing this? I tried setting the attribute I want on the model but it's not in the model when I try to grab it.
view
define([
'text!html/tplDirection.html',
'models/direction',
'core'
], function (template, Direction) {
return Backbone.View.extend({
el: '',
template: _.template(template),
initialize: function (options) {
this.model = new Direction();
this.model.set({rtnm: options.routeNumber});
console.log(this.model);
},
setup: function (routeNumber) {
var self = this;
// self.model.set({rtnm: routeNumber});
$.when(self.model.fetch())
.done(function () {
console.log(self.model.toJSON());
self.render();
})
.fail(function (response) {
console.log(response);
console.log('request for data has failed');
});
},
render: function () {
var data = {
model: this.model.toJSON()
};
this.$el.html(_.template(template, data));
},
Model
define([
'core'
], function () {
return Backbone.Model.extend({
initialize: function (attributes, options) {
console.log(attributes);
},
/* model: Routes,*/
//url: '/apiproxy.php?method=getdirections&rt=',
parse: function (data) {
var parsed = [];
$(data).find('dir').each(function (index) {
var dir = $(this).find('dir').text();
parsed.push({
dir: dir,
});
});
return parsed;
},
fetch: function (options) {
options = options || {};
options.dataType = "xml";
return Backbone.Model.prototype.fetch.call(this, options);
}
});
});
Solved by passing options to model on instantiating. What confused me is that they come through as attributes and not options in the model. How come?
view:
initialize: function (options) {
this.model = new Direction(options);
},
model:
initialize: function (attributes, options) {
console.log(attributes);
},
url: function () {
//'this' now contains attributes
var route = this.get("routeNumber);
//var route = this.attributes.routeNumber;
return '/apiproxy.php?method=getdirections&rt=' + route;
},
how to parse the response value..
i want to get the json value from the json value....but get problem in parsing....
var ListView = Backbone.View.extend({
el: '#app-container',
initialize: function() {
_.bindAll(this,"render");
console.log('ListView init.');
this.counter = 0;
this.collection = new FieldCollection();
this.collection;
this.render(this.collection);
},
events: {
'click #add': 'addItem'
},
render: function(val) {
console.log(val);
console.log('Render called.');
},
});
my json is as follow...
[
{
"name": "qqqqqqqqqqqqqqqqqqq",
"img": "qqqqqqqqqqqqqqqqqqqq"
},
{
"name": "eeeeeeeeeeeeeeeeeee",
"img": "eeeeeeeeeeeeeeeeeee"
},
{
"name": "ggggggggggggggggggg",
"img": "gggggggggggggggggggg"
}
]
my question is that how to parse the response value...
how to access the json value in the view...
var FieldCollection = Backbone.Collection.extend({
defaults: {
model: Field
},
model: Field,
url: 'http://localhost:8080/backbonejs/myjsoncollection.json',
initialize: function() {
console.log('FieldCollection init.');
},
parse: function(response) {
console.log(response);
return response;
}
});
this is the whole code...
$(function(){
var Field = Backbone.Model.extend({
defaults: {
name: "shaleen",
img: "not found",
},
initialize: function() {
// console.log(this.attributes.name);
}
});
var FieldCollection = Backbone.Collection.extend({
defaults: {
model: Field
},
model: Field,
url: 'http://localhost:8080/backbonejs/myjsoncollection.json',
initialize: function() {
console.log('FieldCollection init.');
},
/* parse: function(response) {
console.log(response);
return response;
}*/
});
var ListView = Backbone.View.extend({
el: '#app-container',
initialize: function() {
_.bindAll(this,"render");
console.log('ListView init.');
this.counter = 0;
var jsonfield = new FieldCollection();
jsonfield.fetch();
this.render(jsonfield);
},
render:function(collection){
_.each(collection, function(model){
console.log(model.get('name'));
});
_.each(function(model){
console.log(model.get('name'));
console.log(model.get('img'));
},this);
}
});
var listView = new ListView();
});
The parse function is optional, you only need to implement it, if anything special should happen after you receive the data from the server. To isolate possible sources of errors, I would simplify your approach first by not connecting to your server. Please run the following code:
var Field = Backbone.Model.extend({});
var FieldCollection = Backbone.Collection.extend({
model: Field,
});
var ListView = Backbone.View.extend({
el: '#app-container',
initialize: function() {
this.collection = new FieldCollection();
this.collection.add([{name:'name1',img:'img1'},{name:'name2',img:'img2'}]);
this.render(this.collection);
},
render(collection){
collection.each(function(model){
console.log(model.get('name')+' '+model.get('img'));
},this);
});
If this works, apply the following 2 changes:
Change the collection to include the url:
var FieldCollection = Backbone.Collection.extend({
model: Field,
url='http://localhost:8080/backbonejs/myjsoncollection.json'
});
Change the initialize function of the View to do the fetch:
initialize: function() {
this.collection = new FieldCollection();
this.collection.fetch();
this.render(this.collection);
},
Please run the simplified version first, if that works the extended version.
I am putting together a backbone example in which models are created edited and deleted. I am able to save new models and edits to local storage, but am having a problem getting localstorage to properly display on refresh. It seems to be loading as a single object, and therefore gives me one model regardless of how many were added.
var Thing = Backbone.Model.extend({
defaults: {
title: 'blank'
}
});
var ThingView = Backbone.View.extend({
template: _.template('<b><button id="remove">X</button> <b><button id="edit">Edit</button> <%= title %></b>'),
editTemplate: _.template('<input class="name" value="<%= name %>" /><button id="save">Save</button>'),
events: {
"click #remove": "deleteItem",
"click #edit": "editItem",
"click #save": "saveItem",
},
deleteItem: function () {
console.log('deleted');
this.model.destroy();
this.remove();
},
editItem: function () {
console.log('editing');
this.$el.html(this.editTemplate(this.model.toJSON()));
},
saveItem: function () {
console.log('saved');
editTitle = $('input.name').val();
console.log(editTitle);
this.model.save({
title: editTitle
});
this.$el.html(this.template(this.model.toJSON()));
},
render: function () {
var attributes = this.model.toJSON();
this.$el.append(this.template(attributes));
return this;
}
});
var ThingsList = Backbone.Collection.extend({
model: Thing,
localStorage: new Store("store-name"),
});
var storeVar = localStorage.getItem("store-name");
console.log(storeVar);
var thingsList = new ThingsList;
thingsList.reset(storeVar);
var ThingsListView = Backbone.View.extend({
el: $('body'),
events: {
'click #add': 'insertItem',
},
initialize: function () {
this.render();
this.collection.on("add", this.renderThing, this);
},
insertItem: function (e) {
newTitle = $('input').val();
newThing = new Thing({
title: newTitle
});
this.collection.add(newThing);
newThing.save();
console.log(this.collection.length);
},
render: function () {
_.each(this.collection.models, function (items) {
this.renderThing(items);
}, this);
},
renderThing: function (items) {
var thingView = new ThingView({
model: items
});
this.$el.append(thingView.render().el);
}
});
var thingsListView = new ThingsListView({
collection: thingsList
});
You need to add the items to your collection, and then to read it in you need to call fetch. You also have a couple of extra trailing commas in your objects.
Here's a slightly modified version of your code which seems to work.
var Thing = Backbone.Model.extend({
defaults:{
title:'blank'
}
});
var ThingView = Backbone.View.extend({
//el: $('body'),
template: _.template('<b><button id="remove">X</button> <b><button id="edit">Edit</button> <%= title %></b>'),
editTemplate: _.template('<input class="name" value="<%= name %>" /><button id="save">Save</button>'),
events: {
"click #remove": "deleteItem",
"click #edit": "editItem",
"click #save": "saveItem",
},
deleteItem: function(){
console.log('deleted');
this.model.destroy();
//remove view from page
this.remove();
},
editItem: function(){
console.log('editing');
this.$el.html(this.editTemplate(this.model.toJSON()));
},
saveItem: function(){
console.log('saved');
editTitle = $('input.name').val();
console.log(editTitle);
this.model.save({title: editTitle});
this.$el.html(this.template(this.model.toJSON()));
},
render: function(){
var attributes = this.model.toJSON();
this.$el.append(this.template(attributes));
return this;
}
});
var storeVar = localStorage.getItem("store-name");
var ThingsList = Backbone.Collection.extend({
model: Thing,
localStorage: new Store("store-name")
});
var things = [
{ title: "Macbook Air", price: 799 },
{ title: "Macbook Pro", price: 999 },
{ title: "The new iPad", price: 399 },
{ title: "Magic Mouse", price: 50 },
{ title: "Cinema Display", price: 799 }
];
console.log(things);
var thingsList = new ThingsList;
var ThingsListView = Backbone.View.extend({
el: $('body'),
events: {
'click #add': 'insertItem'
},
initialize: function () {
this.render();
this.collection.on("add", this.renderThing, this);
},
insertItem: function(e){
newTitle = $('input').val();
newThing = new Thing({ title: newTitle });
this.collection.add(newThing);
newThing.save();
//this.model.saveItem;
console.log(this.collection.length);
},
render: function(){
_.each(this.collection.models, function (items) {
this.renderThing(items);
}, this);
},
renderThing: function(items) {
//console.log('added something');
var thingView = new ThingView({ model: items });
items.save();
this.$el.append(thingView.render().el);
}
});
var thingsListView = new ThingsListView( {collection: thingsList} );
thingsList.fetch();
console.log(thingsList.toJSON());
thingsList.reset(things);
Edit: I see you are trying to read in the value stored in local storage under "store-name", the way backbone-localStorage works is that it uses the name of the store (in your case "Store-name") to store the ids of the rest of the models and then saves each model under a combination of the store name and the id, so say you had three models, you would end up with 4 entries in local storage,
localStorage["store-name"] //id1, id2, id3"
localStorage["store-name-id1"] //model with id1
localStorage["store-name-id2"] // model with id2
localStorage["store-name-id3"] // model with id3
EDIT 2
Here's a link to a jsfiddle of your code, to start I'm leaving the line thingsList.fetch(); commented out, uncomment that line and comment out thingsList.add(things); and run it a second time and it should pull the models from local Storage (I left an alert in there).
var Thing = Backbone.Model.extend({
defaults: {
title: 'blank'
}
});
var ThingView = Backbone.View.extend({
template: _.template('<b><button id="remove">X</button> <b><button id="edit">Edit</button> <%= title %></b>'),
editTemplate: _.template('<input class="name" value="<%= name %>" /><button id="save">Save</button>'),
events: {
"click #remove": "deleteItem",
"click #edit": "editItem",
"click #save": "saveItem",
},
deleteItem: function () {
console.log('deleted');
this.model.destroy();
this.remove();
},
editItem: function () {
console.log('editing');
this.$el.html(this.editTemplate(this.model.toJSON()));
},
saveItem: function () {
console.log('saved');
editTitle = $('input.name').val();
console.log(editTitle);
this.model.save({
title: editTitle
});
this.$el.html(this.template(this.model.toJSON()));
},
render: function () {
var attributes = this.model.toJSON();
this.$el.append(this.template(attributes));
return this;
}
});
var ThingsList = Backbone.Collection.extend({
model: Thing,
localStorage: new Store("store-name"),
});
var storeVar = localStorage["store-name-7ee7d1e3-bbb7-b3e4-1fe8-124f76c2b64d"];
console.log(storeVar);
var thingsList = new ThingsList;
//thingsList.reset(storeVar);
var ThingsListView = Backbone.View.extend({
el: $('body'),
events: {
'click #add': 'insertItem',
},
initialize: function () {
thingsList.fetch();
thingsList.toJSON();
this.render();
this.collection.on("add", this.renderThing, this);
},
insertItem: function (e) {
newTitle = $('input').val();
newThing = new Thing({
title: newTitle
});
this.collection.add(newThing);
newThing.save();
console.log(this.collection.length);
},
render: function () {
_.each(this.collection.models, function (items) {
this.renderThing(items);
}, this);
},
renderThing: function (items) {
var thingView = new ThingView({
model: items
});
this.$el.append(thingView.render().el);
}
});
var thingsListView = new ThingsListView({
collection: thingsList
});