binding a button - backbone.js

var ListView = Backbone.View.extend({
el: $('hello'),
events: {
'click .myName': 'namefunc',
},
initialize: function() {
var stuff = new FieldCollection();
stuff.parse();
var self = this;
stuff.fetch({
success: function (collection, response) {
console.log(response);
self.render(response);
return response;
}
});
},
render:function(output){
_.each(output, function(i){
p=i.name;
$(this.el).append("<button class='myName'>"+p+"</button><h1>"+i.img+"</h1><br/>");
},this);
},
namefunc:function(){
alert('hiii');
}
});
how to bind button with class myName with function namefunc.........i tried as shown in the code above...plz help

I refactored your code a bit. I've also put some comments to help you to achieve your goal and understand backbone more.
initialize: function() {
var self = this;
_.bindAll(this, 'render');
this.collection = new FieldCollection();
this.collection.parse();
this.collection.fetch({
success: function (collection, response) {
console.log(response);
self.render();
}
});
},
render:function(){
var self = this;
_.each(this.collection, function(model) {
// here you should create subviews and delegate events within particular view
// i.e:
// self.buttonViews.push(new ButtonView({ model: model}));
// but for now you can use data-id attribute to match the button you clicked
$(self.el).append("<button class='myName' data-id=" + model.id + ">" + model.name + "</button><h1>" + model.img + "</h1><br/>");
});
},
namefunc:function(){
//use data-id attribute we put in button tag earlier to catch the id
//and use this.collection.get('id') function to get the model you want to get parameters of
}

do 'click .myName': 'namefunc', or 'click #myName': 'namefunc',

Related

How to filter a backbone collection and render the results

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

Adding new Item to collection on 'add' triggers only once

I am pretty new to backbone,so probably it is stupid bug.
When I press send button(#send_email_button) , one email is rendered as it should,
but when i press it again, no more emails added.
the only logs i got is:(after second+ push)
:
console.log('adding to collection');
console.log('about to exit');
in other words it does not even enters add handler in collection.
Can someone explain why and how to fix this?
Many thanks!
EDIT: If i delete 1 email that rendered , and press send again, new email added correctly.
Here relevant code:
$(document).ready(function() {
//email model
var EmailModel = Backbone.Model.extend({
defaults: {
id: '',
email_from: '',
email_recipient: '',
email_subject: '',
email_data: '',
is_email_read: '',
email_date: ''
}
});
//email collection
var email_collection = Backbone.Collection.extend({
model: EmailModel,
url: '/fetch_received_emails'
});
var email_collection = new email_collection();
var EmailView = Backbone.View.extend({
model: new EmailModel(),
tagName:'li',
events: {
"click #email_template_view" : "click_email"
},
initialize: function() {
console.log('initializing email view');
this.template = _.template($('#email_template').html());
console.log('finish initializing email view');
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
click_email: function() {
this.model.is_email_read = true;
$('#toggle_part_email').toggleClass('no_display');
},
});
var CollectionView = Backbone.View.extend({
model: email_collection,
el: $('#emails_class'),
initialize: function() {
console.log('init to collection view');
this.model.fetch();
this.render();
this.model.on('change', this.render, this);
this.model.on('add', this.render, this);
this.model.on('remove', this.render, this);
},
render: function(){
console.log('rendering collection');
var that = this,
i;
that.$el.html('');
emails = this.model.toArray();
for (i in emails){
console.log(' printing emails');
console.log(emails[i]);
var new_email_view = new EmailView( {model : emails[i]});
that.$el.append(new_email_view.render().$el);
}
console.log('about to exit collection view');
return this;
}
});
$('#send_email_button').click(function(event){
// event.preventDefault();
var sending_date= new Date();
sending_date = sending_date.toDateString()
//new email to ajax
console.log('adding to collection');
email_collection.add(new EmailModel({
'email_from':$('#email_from').val(),
'email_recipient' :$('#email_recipient').val(),
'email_subject': $('#email_subject').val(),
'email_data':$('#email_data').val(),
'is_email_read':false,
'email_date': sending_date
}));
console.log('about to exit');
return false;
});
//create singelton for the collection view
var c = new CollectionView();
});
Why don't you try to use the click event as the other one? Inside the collectionView use events again.
events: {
"click #send_email_button" : "AnyNameThatYouWant"
},
AnyNameThatYouWant: function() {
//Do all the things
},
Try this.

Backbone appends to list view instead of replacing it

I am producing a single page website with Wordpress and Backbone.js, i have come into a problem with when i fetch new data. It simply adds DOM elements onto the container el rather than replacing them. The collection updates correctly as i can see it has the right amount of elements in the console.
var PostItem = Backbone.Model.extend();
var PostItems = Backbone.Collection.extend({
model: PostItem,
url: '/wp-admin/admin-ajax.php'
});
var postItems = new PostItems();
var PostView = Backbone.View.extend({ /* Model View */
tagName : 'article',
className : 'widget',
template : _.template( $('#widgetPost').html() ),
render: function(){
var attributes = this.model.toJSON();
this.$el.html( this.template( attributes ) );
return this;
}
});
var PostListView = Backbone.View.extend({ /* Collection View */
el : '#content',
initialize: function(){
this.collection.on('add', this.addOne, this);
this.collection.on('reset', this.addAll, this);
},
addOne: function(postItem){
var postView = new PostView({ model : postItem });
this.$el.append( postView.render().el );
},
addAll: function(){
this.collection.forEach(this.addOne, this);
},
render: function(){
this.addAll();
},
});
var postListView = new PostListView({
collection : postItems
});
$(function(){
$('a#posts').click(function(){
postItems.fetch({
data: {
action: 'do_ajax',
fn: 'get_the_posts'
}
});
return false;
});
$('a#pages').click(function(){
postItems.fetch({
data: {
action: 'do_ajax',
fn: 'get_the_pages'
}
});
return false;
});
});
You need to clear out your collectionView's $el! :)
addAll: function(){
this.$el.empty();
this.collection.forEach(this.addOne, this);
}
This should do the trick.

Backbone.js iterating through JSON results from fetch()

I am very new to Backbone and just trying to figure out the way things work. How do I iterate through the "fetched" results?
(function($) {
console.log('Formcontainer init.');
var Field = Backbone.Model.extend({
defaults: {
id: "0",
memberlist_id: "3",
field_name: "sample-field-name",
},
initialize: function() {
console.log('Field model init.');
}
});
var FieldCollection = Backbone.Collection.extend({
defaults: {
model: Field
},
model: Field,
url: 'http://localhost:8888/getstuff/3.json',
initialize: function() {
console.log('FieldCollection init.');
}
});
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.fetch();
//this.collection.bind('reset', function() { console.log('xxx')});
//this.collection.fetch();
this.render();
},
events: {
'click #add': 'addItem'
},
render: function() {
var self = this;
console.log('Render called.');
},
addItem: function() {
this.counter++;
this.$("ul").append("<li>hello world" + this.counter + "</li>");
}
});
var listView = new ListView();
})(jQuery);
I get this in my Firebug console:
Formcontainer init.
ListView init.
FieldCollection init.
GET http://localhost:8888/getstuff/3.json 200 OK
Render called.
Field model init.
Field model init.
Field model init.
Field model init.
Field model init.
It seems that the fetch() was called - since "Field model init." is in the console 5 times. But how to I output that? I would want to append the items in an unordered list.
Thanks!
Bind the reset event to your render function...
this.collection.bind('reset', this.render, this);
This gets triggered after the fetch is complete, so you can create the list...
render: function() {
var self = this;
console.log('Render called.');
this.collection.each(function(i,item) {
this.$el.append("<ul>" + item.get("field_name") + "</ul>");
});
},

Backbone view, initialize and render

I have a backbone view which load subview. When I load a subview, I would like to show a loader when the view fetch needed datas and hide the loader when the view is ready to render.
I did something like this :
var appView = Backbone.View.extend({
showLoader: function() {
// Code to show loader
},
hideLoader: function() {
// Code to hide loader
 },
loadSubView: function() {
this.showLoader();
var myView = new MySubView();
this.$el.html(myView.render().el);
this.hideLoader();
}
});
For now, my sub-view load a collection and is implemented like this :
var mySubView = Backbone.View.extend({
initialize: function() {
this.myCollection.fetch({
async: false
});
},
render: function() {
// Code to render
}
});
My sub view load the collection synchronously because it is the only way I found to know when my view is "ready" to render but I think this is not the best way to use Backbone.
What schould I do ?
There are several ways to do it.
You can explicitly use the pubsub pattern. Something like this:
var AppView = Backbone.View.extend({
showLoader: function() {
console.log('show the spinner');
},
hideLoader: function() {
console.log('hide the spinner');
},
loadSubView: function() {
this.showLoader();
var subView = new SubView();
subView.on('render', this.hideLoader);
this.$el.html(subView.render().el);
}
});
var SubView = Backbone.View.extend({
render: function() {
console.log('a subView render');
this.trigger('render');
return this;
}
});
var appView = new AppView({el: $('body')});
appView.loadSubView();
http://jsfiddle.net/theotheo/qnVhy/
You can attach a function to the ajaxStart/ajaxStop events on the
spinner itself:
var AppView = Backbone.View.extend({
initialize: function() {
var _this = this;
this.$('#spinner')
.hide()
.ajaxStart(_this.showLoader)
.ajaxStop(_this.hideLoader);
}
...
}
Or you can use jQuery.ajaxSetup:
var AppView = Backbone.View.extend({
initialize: function() {
var _this = this;
jQuery.ajaxSetup({
beforeSend: _this.showLoader,
complete: _this.hideLoader,
success: function() {}
});
}
...
}

Resources