$el.append not working in backbone.js - backbone.js

console.log('Loaded inedx.js-->');
console.log(jQuery);
(function($){
console.log('In immediate block');
//Create new tweet view
var Tweet = Backbone.Model.extend({
defaults: function(){
return {
name : 'defaultName',
status : 'default status'
}
}
});
var TweetList = Backbone.Collection.extend({
model :Tweet
});
var TweetView = Backbone.View.extend({
model : new Tweet(),
tagName : 'div',
initialize : function(){
this.template = _.template($('#tweet-template').html());
},
render : function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
var tweets = new TweetList();
var TweetsView = Backbone.View.extend({
model : tweets,
tagName : 'div',
el : $('#allTweetContainer'),
initialize: function(){
this.model.on('add',this.render,this);
},
render : function(){
var self = this;
_.each(this.model.toArray(),function(tweet,i){
self.$el.append((new TweetView({model:tweet})).render().$el.html());
});
return this;
}
});
$(document).ready(function (){
tweets.add(new Tweet({
status : 'status1',
author : 'author1'
}));
var tweet = new Tweet({
status : 'status1-----',
author : 'author1-------'
});
//console.log(new TweetView());
//$('#allTweetContainer').append( _.template($('#tweet-template').html(),tweet.toJSON()));
tweets.add(new Tweet({
status : 'status2',
author : 'author2'
}));
tweets.add(new Tweet({
status : 'status3',
author : 'author3'
}));
tweets.add(new Tweet({
status : 'status4',
author : 'author4'
}));
var tweetApp = new TweetsView();
tweetApp.render();
console.log(tweets.toJSON());
});
})(jQuery);
I am not able to render TweetsView.
Instead of : self.$el.append
When I used : `$('#allTweetContainer').append
it worked. But ideally it should work with self.$el.append.
I believe there must be something extra needs to be done to get proper $el which should be a jQuery variable pointing to the given el.
Any pointers would really helpful. Thanks in advance.

You should declare el as string and not as jQuery selector. So your TweetsView should look like this:
var TweetsView = Backbone.View.extend({
model : tweets,
tagName : 'div',
el : '#allTweetContainer',
initialize: function(){
this.model.on('add',this.render,this);
},
render : function(){
var self = this;
_.each(this.model.toArray(),function(tweet,i){
self.$el.append((new TweetView({model:tweet})).render().$el.html());
});
return this;
}
});
when appending the TweetView to TweetsView, you could also do this:
_.each(this.model.toArray(),function(tweet,i){
self.$el.append((new TweetView({model:tweet})).render().el);
});

Related

Why my simple view is not working

I have this JS code:
$(function() {
var LinkView = new Backbone.View.extend({
render: function() {
this.$el.html(this.model.get('text'));
}
});
var Link = Backbone.Model.extend({
text: 'message',
say: function() {
console.log(this.text);
}
});
var l = new Link();
l.say();
var v = new LinkView({model : l, el : 'body'});
v.render();
});
I am waiting to get 'message' on the browser, but get the error TypeError: r.apply is not a function in the console. Why and how can I fix it ?
Please paste this, new was the problem in View, also did slight modification. it works now..
$(function() {
var Link = Backbone.Model.extend({
defaults : {
text: 'default message'
},
say: function() {
console.log(this.get('text'));
}
});
var LinkView = Backbone.View.extend({
render : function() {
this.$el.html(this.model.get('text'));
}
});
var l = new Link({text:'custom text message'});
l.say();
var v = new LinkView({model : l, el : 'body'});
v.render();
});

underscore template is not working in backbone

In my view.js I am calling the wine-list-tpl (template), as below you can see this. But nothing is showing to the index page. Please help.
IN index.html
<script type="text/template" id="wine-list-tpl">
Hello world
<%= name %>
</script>
.......
<div class="wine-list"></div>
IN view.js
var WineLists = Backbone.View.extend({
el:'.wine-list',
template : _.template($('#wine-list-tpl').html()),
render: function(){
console.log("rendering is ok");
this.$el.html( this.template( this.model.toJSON() ));
return this;
}
});
var WineList = Backbone.View.extend({
model:wines,
initialize: function(){
var self=this;
wines.fetch();
_.each(this.model.toArray(), function(wine, i){
$('#wine-list').append((new WineLists({ model : wine })).render().$el);
});
}
});
var wineListView = new WineList();
I have added some data in to my local storage and i just want to show those data to that particular div element.
In WineLists view i am getting all those data. means when i am writing, console.log(this.model.get('name')); I got my desired data, but i only want to show those data through template to that particular div. what should i do, please suggest.
var WineLists = Backbone.View.extend({
model: new Wine(),
template : _.template($('#myTpl').html()),
render: function(){
//console.log(this.model.get('name'));
this.$el.html(this.template(this.model.toJSON()));
return this;
} });
var WineList = Backbone.View.extend({
model:wines,
el:'.wineDiv',
initialize: function(){
var self=this;
wines.fetch();
_.each(this.model.toArray(), function(wine, i){
self.$el.append((new WineLists({ model : wine })).render().$el);
});}});
var wineListView = new WineList();
//please check ur DOM manipulation i think there is some error in ur HTML try to change call //sequence
This is how your code should have been for expected results.
var WineLists = Backbone.View.extend({
el: '.wine-list',
render: function () {
var _self = this;
this.collection.each(function (model) {
var view = new WineListItemView({
model: model
})
view.render();
view.$el.appendTo(_self.el);
})
return this;
}
});
var WineListItemView = Backbone.View.extend({
template: _.template($('#wine-list-tpl').html()),
render: function () {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
var wines = new Backbone.Collection([{
name: 'wine1'
}, {
name: 'wine2'
}])
var wineListView = new WineLists({
collection: wines
});
wineListView.render()

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.

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.

Backbone, one field not set when calling view.render after model.save

I have the following problem. On a user-event (click on .twitterDefault) I call save event with
twitter : {
handle : handle,
ignore : false
}
Then the success function gets called and I set fields on the model (klout, twitter and tester). All fields are set (logging statements all print out appropiate objects.
However, then I call view.render() and here twitter is not set anymore. I have no idea why, there is no sync happening after the save so twitter does not get overwritten (additionally I made sure twitter is also saved on the server before the success method gets called).
Any help greatly appreciated!
Code as follows (stripped to improve readability)
$(function() {
var ContactModel,
ContactModelCollection,
ContactView,
ContactCollectionView,
contacts,
contactCollectionView;
//base model
ContactModel = Backbone.Model.extend({
defaults : {
},
initialize : function() {
}
});
ContactModelCollection = Backbone.Collection.extend({
model : ContactModel,
url : '/api/contacts',
comparator : function(contact) {
return contact.get('strength_of_relationship');
},
initialize : function() {
}
});
ContactView = Backbone.View.extend({
tagName : 'li', //attempting to create a new element
render: function() {
var compiled_tmpl = _.template($('#contact-template').html());
var html = compiled_tmpl(this.model.toJSON());
console.log('model.get("twitter")=('+JSON.stringify(this.model.get('twitter)'))+')');
console.log('model.get("klout")=('+JSON.stringify(this.model.get('klout'))+')');
console.log('model.get("tester")=('+JSON.stringify(this.model.get('tester'))+')');
this.$el.html(html);
console.log('rendered view successfully)');
return this;
},
initialize: function() {
console.log('contactView initalized');
this.model.bind('change', this.render, this);
this.model.bind('destroy', this.remove, this);
},
events: {
'click .twitterDefault' : 'assignDefaultTwitterHandle',
},
assignDefaultTwitterHandle : function(event) {
var handle = $(event.currentTarget).data('twitter');
this.assignTwitterHandle(handle);
},
assignTwitterHandle : function(handle) {
console.log('model assignTwitterHandle. handle='+handle+')');
var view = this,
model = view.model;
model.save({
twitter : {
handle : handle,
ignore : false
},
id : model.get('id')
}, {
error : function() {
console.log('saving twitter handle failed');
},
success : function(model, response) {
console.log('response=('+JSON.stringify(response)+')');
if(response.error) {
console.log('error on server ='+response.error);
}
if(response.twitter) {
console.log('twitter is set');
var twitter = {
handle : handle,
tweet : response.twitter,
age : new Date()
};
console.log('setting twitter to '+JSON.stringify(twitter));
model.set('twitter', twitter);
model.set('tester', 'tester');
console.log('twitter after setting it = '+JSON.stringify(model.get('twitter')));
console.log('view\'s model twitter after setting it = '+JSON.stringify(view.model.get('twitter')));
}
if(response.klout) {
console.log('klout is set');
var klout = {
topics : response.klout
}
console.log('setting klout to '+JSON.stringify(klout));
model.set('klout', klout);
}
if(response.twitter || response.klout) {
console.log('Rerendering view after setting klout/twitter');
view.render();
}
}
});
}
});
contacts = new ContactModelCollection;
ContactCollectionView = Backbone.View.extend({
el : $('#suggestions-list'),
initialize : function(){
contacts.bind('add', this.addOne, this);
contacts.bind('reset', this.addAll, this);
contacts.bind('all', this.render, this);
},
render : function(){
console.log('contactcollectionview render');
},
addOne : function(contact) {
console.log('addOne');
var view = new ContactView({model: contact});
var el = view.render().el;
console.log('el=('+el+')');
$('#suggestions-list').append(el);
},
addAll : function() {
console.log('addAll');
contacts.each(this.addOne);
}
});
contactCollectionView = new ContactCollectionView;
App.contacts = contacts;
App.contactCollectionView = contactCollectionView; });
I guess the problem is the scope of the render function.
Depending from where is called, this takes a different value.
To warranty that always this is pointing to the View scope, add to your initialize:
_.bindAll(this,"render");
Also, it's not good habit to call view.render manually. You should let the events do their work. Model save already triggers some events. Just listen to them to update your View.

Resources