View not initializing in Backbone.js - javascript

Ive created a simple backbone app that gets data from MySQL database about users to display in a view called LeaderBoardView.
Below is the HTML code for the view,
<body>
<div id="container"></div>
<h1>Leaderboard</h1>
<table class="table" id="modtable">
<tr>
<th>Username</th>
<th>Level</th>
</tr>
</table>
<div id="bbcontent"></div>
Im trying to get data and populate inside the div with bbcontent as the id.
Below is my Backbone model, collection and view,
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-
min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.3/backbone-min.js">
</script>
<script language="javascript">
$(document).ready(function() {
alert("heyyyyyy")
//model
var User = Backbone.Model.extend({
idAttribute: "userId",
defaults: {
username: null,
userLevel: null
}
});
//collection
var Users = Backbone.Collection.extend({
model: User,
url: "/CW2/ASSWDCW2/cw2app/index.php/Leaderboard/leaderboard",
});
var usersC = new Users();
var LeaderboardDeetsView = Backbone.View.extend({
model: usersC,
el: $('#bbcontent'),
intialize: function() {
alert("asndasnxdjksa")
usersC.fetch({
async: false
})
this.render()
},
render: function() {
var self = this;
usersC.each(function(c) {
var block = "<div class='name'><h1>" + c.get('username') + "</h1></div>"
self.$el.append(block)
})
}
})
var leaderboardDeetsView = new LeaderboardDeetsView();
});
Problem with this code :
The LeaderboardDeetsView isn't being called hence the collection fetch function inside the initialize function of the LeaderboardDeetsView isn't being called.How can I correct my code? Please help

Related

Model not accesseble outside namespace

Im trying to bind my knockout array to a table, but cant reach the model outside the javascript function.
Here is my javascript code
(function (conf, $, undefined) {
var model = { menuRows : [], orderRows : [], menuDetails : null };
conf.getMenuRows = function () {
$.get("/orderpackage/row", function (data) {
model.orderRows = data;
});
};
conf.getMenuRows();
ko.applyBindings(model);
}(window.conf = window.conf || {}, jQuery));
And this is the HTML
<table class="table table-hover table-bordered">
<thead>
<tr>
<th>Beskrivning</th>
</tr>
</thead>
<tbody data-bind="foreach: model.orderRows">
<tr>
<td data-bind="text: description"></td>
</tr>
</tbody>
</table>
model.orderRows is not found.
Cant understand what im doing wrong here.
your models are not using the observable array function. You will need something like the following:
function Model() {
var self = this();
self.menuRows = ko.observableArray();
self.orderRows = ko.observableArray();
self.getMenuRows = function() {
$.get("/orderpackage/row", function (data) {
self.orderRows = ko.observableArray(data)
});
....
}
Then you can call
(function (conf, $, undefined) {
var model = Model();
model.getMenuRows();
ko.applyBindings(model);
}(window.conf = window.conf || {}, jQuery));
Then you should be able to bind like you are doing in your HTML.
More tutorials can be found here: http://learn.knockoutjs.com/
If you then want to bind to items in each of the array elements, the description for example, you will need to create an additional model definition for the row and parse the data returned from your api to the model type.
I found a good solution
(function (conf, $, undefined) {
var model = {
menuRows: ko.observableArray([]),
order: ko.observableArray([]),
menuDetails: ko.observable()
};
conf.getMenuRows = function () {
$.ajax({
url: "/orderpackage/row",
cache: false,
type: "GET",
datatype: "json",
contenttype: "application/json;utf8"
}).done(function (data) {
model.order(data.model);
});
};
conf.getMenuRows();
ko.applyBindings(model);
}(window.conf = window.conf || {}, jQuery));

Rendering a table with Backbone

I need help with my code, I'm trying to learn Backbone for my Social Project. I'm trying to render a view from a collection that I got from an API (deployd API)
Here is the HTML code for the table:
<div class="container-fluid">
<table id= "teachers">
<thead>
<tr>
<th>Name</th>
<th>Last Name</th>
<th>Code</th>
<th>Last time online</th>
</tr>
</thead>
<tbody id="table-body"></tbody>
</table>
</div>
<script type="text/template" id="teacher-template">
<td><%= name %></td>
<td><%= lastname %></td>
<td><%= code %></td>
<td><%= lastactivity %></td>
</script>
Here is the JS code:
var TeacherModel = Backbone.Model.extend({
defaults: {
id:'',
name: '',
lastname: '',
code: '',
lastactivity: ''
}
});
var TeacherCollection = Backbone.Collection.extend({
url: "/teachers",
model: TeacherModel
});
var teachercollection = new TeacherCollection();
teachercollection.url = '/teachers';
teachercollection.fetch({
success: function(collection, response) {
console.log("Done!!");
}, error: function(collection, response) {
alert(response);
}
});
var TeachersView = Backbone.View.extend({
el: '#table-body',
initialize: function() {
this.render();
},
render: function() {
this.$el.html('');
teachercollection.each(function(model) {
var teacher = new TeacherView({
model: model
});
this.$el.append(teacher.render().el);
}.bind(this));
return this;
}
});
var TeacherView = Backbone.View.extend({
tagName: 'tr',
template: _.template($('#teacher-template').html()),
render: function() {
this.$el.html(this.template(this.model.attributes));
return this;
}
});
// Launch app
var app = new TeachersView;
So my question is, how I can pass a collection to a view, or a model of the collection to a view? I want to render the data in each row from the table. The browser gets the collection, as you can see here:
I've been trying for days, and I just can't understand the logic, I have read the documentation, and a little of the Addy Osmani's book but just can't get my head on it, can someone explain it to me? Been looking for answers in this site but some on them include some "add models" stuff, which confuse me more.
(The parameters of the model in the image, differ from the code. I'd translate to make it more easy to understand.)
how I can pass a collection to a view, or a model of the collection to a view?
You are already doing that in your code:
var teacher = new TeacherView({
model: model
});
Here you're passing a model to view's constructor using model option.
You can pass a collection to view via it's constructor like:
var app = new TeachersView({
collection:teachercollection
});
Which you can access inside the view via this.collection and this.model respectively.
var TeachersView = Backbone.View.extend({
el: '#table-body',
initialize: function() {
this.render();
},
render: function() {
this.$el.html('');
this.collection.each(function(model) {
this.$el.append(new TeacherView({
model: model
}).el);
},this);
return this;
}
});
Note that fetch() is asynchronous, so you'll need to wait till it succeeds before rendering the view.
See the suggestions in this answer regarding the changes I made to your render method.
this answer might help understanding a thing or two.

Hello World - Backbone + Firebase + Backfire

I'm trying to create a simple hello world with backbone and firebase(using backfire). The code is working to insert data to firebase, but when I try to get data and fill the template, it says "Uncaught ReferenceError: firstName is not defined". On debug I can see the object with the data but I don't know how to provide the template with this object.
Here is the code:
$(document).ready(function(){
var registerModel = Backbone.Model.extend({
defaults: {
firstName: '',
lastName: ''
}
});
var registerColletion = Backbone.Firebase.Collection.extend({
model:registerModel,
firebase: new Firebase("https://XXXXXXXX.firebaseio.com/")
});
var registerView = Backbone.View.extend({
el: $("#myTest"),
itemTemplate: _.template($('#item-template').html()),
events: {
"click #btnSave": "saveToFirebase"
},
initialize: function () {
this.listenTo(registerList, 'add', this.render);
},
render: function(){
$('#divContent').html(this.itemTemplate(this.model.toJSON()));
},
saveToFirebase: function () {
registerList.add({firstName: $("#txtFirstName").val(), lastName: $("#txtLastName").val()});
}
});
var registerList = new registerColletion;
var app = new registerView({model:registerList});
});
The exact point of the exception is on render function:
render: function(){
$('#divContent').html(this.itemTemplate(this.model.toJSON()));
},
The template:
<script type="text/template" id="item-template">
<div class="view">
<p>
<%- firstName %> <%- lastName %>
</p>
</div>
</script>
Can anyone please help me? I think I'm missing something (probably obvious) but I can't see it.
Thank you!
When you create the registerView you're telling it that the underlying model is a registerList (not a registerModel)
var app = new registerView({model:registerList});
Therefore, when the render function is called, it's looking for the firstName property of a registerList, and that property doesn't exist.
Seems like you've got Models and Collections mixed up

how and where to initialize jquery datatable in backbone view

My html template look like this:
<script type="text/template" id="players-template">
<table id="example" class="table table-striped table-bordered table-condensed table-hover">
<thead>
<tr>
<th>Name</th>
<th>group</th>
<th></th>
</tr>
</thead>
<tbody id="playersTable"></tbody>
</table>
</script>
<script type="text/template" id="player-list-item-template">
<td><#= name #></td>
<td>
<# _.each(hroups, function(group) { #>
<#= group.role #>
<# }); #>
</td>
</script>
My backbone view is as follows:
playerView = Backbone.View.extend({
template: _.template( $("#player-template").html() ),
initialize: function ()
if(this.collection){
this.collection.fetch();
},
render: function () {
this.$el.html( this.template );
this.collection.each(function(player) {
var itemView = new app.PlayerListItemView({ model: player });
itemView.render();
this.$el.find('#playersTable').append(itemView.$el);
},this
});
// view to generate each player for list of players
PlayerListItemView = Backbone.View.extend({
template: _.template($('#player-list-item-template').html()),
tagName: "tr",
render: function (eventName) {
this.$el.html( this.template(this.model.toJSON()) );
}
});
The above code works perfectly. Now, I want to use apply jquery datatable plugin wtih bootstrap support. You can find detail here :http://www.datatables.net/blog/Twitter_Bootstrap_2
So, I just added the line inside render as:
render: function () {
this.$el.html( this.template );
this.collection.each(function(player) {
var itemView = new app.PlayerListItemView({ model: player });
itemView.render();
this.$el.find('#playersTable').append(itemView.$el);
$('#example').dataTable( {
console.log('datatable');
"sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i> <'span6'p>>",
"sPaginationType": "bootstrap",
"oLanguage": {
"sLengthMenu": "_MENU_ records per page"
},
"aoColumnDefs": [
{ 'bSortable': false, 'aTargets': [ 2 ] }
]
} );
},this);
},
Now, the jquery datable is not initialized. They just diisplay normal table.
where should I intialized the table to apply jquery datatable?
they worked perfectly without backbone.
Most likely, the jQuery plugin needs the elements to be on the page to work. You don't show where you are calling render on that view, but I am going to assume you are doing something like this:
var view = new PlayerView();
$('#foo').html(view.render().el); // this renders, then adds to page
If this is true, then using the plugin inside render is too early, since the view's html is not yet added to the page.
You can try this:
var view = new PlayerView();
$('#foo').html(view.el); // add the view to page before rendering
view.render();
Or you can try this:
var view = new PlayerView();
$('#foo').html(view.render().el);
view.setupDataTable(); // setup the jQuery plugin after rendering and adding to page

Why doesn't my simple Ember.js Handlebars helper work when loading data asynchronously?

I have a simple Handlebars helper which simply formats a money value. The helper works property when I test with static data, but not when I load data asynchronously. In other words, {{totalBillable}} will output the expected amount, but {{money totalBillable}} will output zero. But only when the data is loaded via an ajax call. What the heck am I doing wrong?
I've tried to pare the code down as much as possible, and also created a jsfiddle here:
http://jsfiddle.net/Gjunkie/wsZXN/2/
This is an Ember application:
App = Ember.Application.create({});
Here's the handlebars helper:
Handlebars.registerHelper("money", function(path) {
var value = Ember.getPath(this, path);
return parseFloat(value).toFixed(2);
});
Model:
App.ContractModel = Ember.Object.extend({});
App Controller:
App.appController = Ember.Object.create({
proprietor: null,
});
Contracts Controller (manages an array of contracts):
App.contractsController = Ember.ArrayController.create({
content: [],
totalBillable: function() {
var arr = this.get("content");
return arr.reduce(function(v, el){
return v + el.get("hourlyRate");
}, 0);
}.property("content"),
When the proprietor changes, get new contract data with an ajax request. When getting data asynchronously, the handlebars helper does not work.
proprietorChanged: function() {
var prop = App.appController.get("proprietor");
if (prop) {
$.ajax({
type: "POST",
url: '/echo/json/',
data: {
json: "[{\"hourlyRate\":45.0000}]",
delay: 1
},
success: function(data) {
data = data.map(function(item) {
return App.ContractModel.create(item);
});
App.contractsController.set("content", data);
}
});
}
else {
this.set("content", []);
}
}.observes("App.appController.proprietor")
});
If I use this version instead, then the Handlebars helper works as expected:
proprietorChanged: function() {
var prop = App.appController.get("proprietor");
if (prop) {
var data = [{
"hourlyRate": 45.0000}];
data = data.map(function(item) {
return App.ContractModel.create(item);
});
App.contractsController.set("content", data);
}
else {
this.set("content", []);
}
}.observes("App.appController.proprietor")
View:
App.OverviewTabView = Ember.TabPaneView.extend({
totalBillableBinding: "App.contractsController.totalBillable"
});
Kick things off by setting a proprietor
App.appController.set("proprietor", {
ID: 1,
name: "Acme"
});
Template:
<script type="text/x-handlebars">
{{#view App.OverviewView viewName="overview"}}
<div class="summary">
Total Billable: {{totalBillable}}<br/>
Total Billable: {{money totalBillable}}<br/>
</div>
{{/view}}
</script>
when using a helper, handlebars does not emit metamorph tags around your helper call. this way, this part of the template is not re-rendered because there is no binding
to manually bind part of a template to be re-rendered, you can use the bind helper:
<script type="text/x-handlebars">
{{#view App.OverviewView viewName="overview"}}
<div class="summary">
Total Billable: {{totalBillable}}<br/>
Total Billable: {{#bind totalBillable}}{{money this}}{{/bind}}<br/>
</div>
{{/view}}
</script>

Categories

Resources