In the script below are various routes and view and routes events built with Backbone.js
Why is it, that all of the routes work as I expect except the last one 'products'.
I originally had it as a very different function but realized it wasn't firing off, but not even as a duplicate of the other views and routes it still wont work.
Anyone have an idea why?
Thanks you!
I am also very new to Backbone.
Rich
<!doctype html>
<html>
<head>
<title>Undie Couture by Lauren Copeland</title>
<link type="text/css" rel="stylesheet" href="/assets/css/museosans_500_macroman/stylesheet.css" />
<link type="text/css" rel="stylesheet" href="/assets/css/bootstrap/bootstrap.css" />
<link type="text/css" rel="stylesheet" href="/assets/css/site/front-styles.css" />
</head>
<body>
<div id="wrapper">
<div class="content">
<header>
<div class="container">
<div id="logo"></div>
<nav>
<ul>
<li>shop</li>
<li>contact</li>
<li>about</li>
<li>wholesale</li>
</nav>
</nav>
</div>
</header>
<div class="container">
<div class="page" id="first" style="display:none;"></div>
<div class="page"></div>
</div>
</div>
</div>
</body>
<script type="text/template" id="title-temp">
<%= title %>
</script>
<script type="text/template" id="logo-temp">
<img src="/assets/img/logo-strip.png" />
</script>
<script type="text/template" id="home-temp">
<%= title %>
</script>
<script type="text/template" id="page-temp">
<h1><%= page.pluck('title') %></h1>
<div id="body">
<%= page.pluck('body') %>
</div>
</script>
<script type="text/template" id="product-temp">
<h1><%= page.pluck('name') %></h1>
<div id="body">
<%= page.pluck('description') %>
</div>
</script>
<script type="text/javascript" src="/assets/js/libs/jquery/jquery.js"> </script>
<script type="text/javascript" src="/assets/js/libs/underscore/underscore.js"></script>
<script type="text/javascript" src="/assets/js/libs/backbone/backbone-min.js"></script>
<script type="text/javascript" src="/assets/js/libs/bootstrap/bootstrap.js"></script>
<script type = "text/javascript">
var Router = Backbone.Router.extend({
routes: {
"home": "home",
"about": "about",
"contact": "contact",
"wholesale": "wholesale",
"products": "products"
}
});
var Page = Backbone.Model.extend({
initialize: function() {
console.log('Page model loaded');
},
defaults: {
"id": "",
"title": "",
"body": "",
"slug": ""
},
urlRoot: '/backbone/page'
});
var Pages = Backbone.Collection.extend({
initialize: function() {
console.log('pages collection loaded');
},
url: '/backbone/page'
});
var HomeView = Backbone.View.extend({
template: $('#standard').html(),
el: '.page:first',
change: function() {
$('.page').fadeOut('slow');
},
render: function() {
logo = $('#logo-temp').html();
$('#logo').html(logo);
$('.content').attr('id', 'home');
var that = this;
that.change();
compiled = _.template($('#home-temp').html(), {
title: ''
});
that.$el.html(compiled);
}
});
var AboutView = Backbone.View.extend({
template: $('#standard').html(),
el: '.page:first',
change: function() {},
render: function() {
console.log('render')
var that = this;
logo = $('#logo-temp').html();
$('#logo').html(logo);
$('.content').attr('id', 'about');
aboutPage = new Pages();
aboutPage.fetch({
data: {
id: 3
},
success: function() {
$('#first').fadeOut({
duration: 400,
complete: function() {
console.log(aboutPage.models)
compiled = _.template($('#page-temp').html(), {
page: aboutPage
});
that.$el.html(compiled).delay(300).fadeIn();
}
});
}
});
}
});
var ContactView = Backbone.View.extend({
template: $('#standard').html(),
el: '.page:first',
change: function() {
$('.page').fadeOut();
},
render: function() {
var that = this;
logo = $('#logo-temp').html();
$('#logo').html(logo);
$('.content').attr('id', 'contact');
contactPage = new Pages();
contactPage.fetch({
data: {
id: 2
},
success: function() {
$('#first').fadeOut({
duration: 400,
complete: function() {
console.log(contactPage.models)
compiled = _.template($('#page-temp').html(), {
page: contactPage
});
that.$el.html(compiled).delay(300).fadeIn();
}
});
}
});
}
});
var WholesaleView = Backbone.View.extend({
template: $('#standard').html(),
el: '.page:first',
change: function() {},
render: function() {
console.log('render')
var that = this;
logo = $('#logo-temp').html();
$('#logo').html(logo);
$('.content').attr('id', 'about');
wholePage = new Pages();
wholePage.fetch({
data: {
id: 4
},
success: function() {
$('#first').fadeOut({
duration: 400,
complete: function() {
console.log(wholePage.models)
compiled = _.template($('#page-temp').html(), {
page: wholePage
});
that.$el.html(compiled).delay(300).fadeIn();
}
});
}
});
}
});
var ProductView = Backbone.View.extend({
template: $('#standard').html(),
el: '.page:first',
change: function() {},
render: function() {
var that = this;
logo = $('#logo-temp').html();
$('#logo').html(logo);
$('.content').attr('id', 'about');
wholePage = new Pages();
wholePage.fetch({
data: {
id: 4
},
success: function() {
$('#first').fadeOut({
duration: 400,
complete: function() {
console.log(wholePage.models)
compiled = _.template($('#page-temp').html(), {
page: wholePage
});
that.$el.html(compiled).delay(300).fadeIn();
}
});
}
});
}
});
var router = new Router();
var page_model = new Page();
var page_col = new Pages();
var home = new HomeView();
var about = new AboutView();
var contact = new ContactView();
var wholesale = new WholesaleView();
var products = new ProductView();
router.on('route:home', function() {
home.render();
});
router.on('route:about', function() {
about.render();
});
router.on('route:contact', function() {
contact.render();
});
router.on('route:wholesale', function() {
wholesale.render();
});
router.on('route:products', function() {
products.render();
});
Backbone.history.start();
</script>
Your anchor tag for shops has a trailing /
<a href="/#/products/">
Should be
<a href="/#/products">
Removing that made the route work for me.
Related
I need to render my template templates/page.html:
<section class="section">
<div class="container">
<h1 class="title"><%= title %></h1>
<div><%= content %></div>
<div><%= pages %></div>
</div>
</section>
into my div element with page-content id:
// Underscore mixins
_.mixin({templateFromUrl: function (url, data, settings) {
var templateHtml = "";
this.cache = this.cache || {};
if (this.cache[url]) {
templateHtml = this.cache[url];
} else {
$.ajax({
url: url,
method: "GET",
async: false,
success: function(data) {
templateHtml = data;
}
});
this.cache[url] = templateHtml;
}
return _.template(templateHtml, data, settings);
}});
// Models
var PageState = Backbone.Model.extend({
defaults: {
title: "",
subtitle: "",
content: "",
pages: "",
state: "games"
}
});
var pageState = new PageState();
// Routers
var PageRouter = Backbone.Router.extend({
routes: {
"": "games",
"!/": "games",
"!/games": "games",
"!/users": "users",
"!/add-user": "add_user"
},
games: function () {
select_item($("#games"));
console.log("games");
pageState.set({ state: "games" });
},
users: function () {
select_item($("#users"));
console.log("users");
pageState.set({ state: "users" });
},
add_user: function () {
console.log("add_user");
}
});
var pageRouter = new PageRouter();
// Views
var Page = Backbone.View.extend({
templates: {
"page": _.templateFromUrl("/templates/page.html")
},
initialize: function () {
this.render();
},
render: function () {
var template = this.templates["page"](this.model.toJSON());
this.$el.html(template);
return this;
}
});
$(function () {
var page = new Page({
el: '#page-content',
model: pageState
});
});
// Run backbone.js
Backbone.history.start();
// Close mobile & tablet menu on item click
$('.navbar-item').each(function(e) {
$(this).click(function() {
if($('#navbar-burger-id').hasClass('is-active')) {
$('#navbar-burger-id').removeClass('is-active');
$('#navbar-menu-id').removeClass('is-active');
}
});
});
// Open or Close mobile & tablet menu
$('#navbar-burger-id').click(function () {
if($('#navbar-burger-id').hasClass('is-active')) {
$('#navbar-burger-id').removeClass('is-active');
$('#navbar-menu-id').removeClass('is-active');
} else {
$('#navbar-burger-id').addClass('is-active');
$('#navbar-menu-id').addClass('is-active');
}
});
// Highlights an item in the main menu
function select_item(sender) {
$("a.v-menu-item").removeClass("is-active");
sender.addClass("is-active");
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/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.3.3/backbone-min.js"></script>
<body>
<section class="hero is-primary is-medium">
<div class="hero-head">
<nav id="navMenu" class="navbar">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item is-size-2">Virto</a>
<span id="navbar-burger-id" class="navbar-burger burger" data-target="navbar-menu-id">
<span></span>
<span></span>
<span></span>
</span>
</div>
<div id="navbar-menu-id" class="navbar-menu">
<div class="navbar-end">
<a id="games" href="#!/games" class="navbar-item v-menu-item is-active">Games</a>
<a id="users" href="#!/users" class="navbar-item v-menu-item">Users</a>
<span class="navbar-item">
<a href="#!/add-user" class="button is-primary is-inverted">
<span class="icon">
<i class="fas fa-user-circle"></i>
</span>
<span>Add user</span>
</a>
</span>
<div>
</div>
</div>
</nav>
</div>
</section>
<div id="page-content"></div>
</body>
But my content doesn't load... I'm a noobie in backbone.js still so can someone explain what do I doing wrong and how to fix?
ADDED
I have checked my script in debugger. It loads a template and finds my div in the render() function but I can't see any result in browser after, my div is empty still.
I created a plunker with your code, and it works fine for me: link
I think you only forgot to initialize your model:
// Models
var PageState = Backbone.Model.extend({
defaults: {
title: "Title - 1",
subtitle: "Subtitle - 1",
content: "Content",
pages: "1",
state: "games"
}
});
I am new to BackBone and am trying to practice rendering from a collection. I know that none of this is supposed to be done in HTML, but a friend gave me this prompt and I want to get it to work. I've done lots of debugging, but I can't tell why Pond View isn't rendering properly?
<html>
<head>
<title>Pond Maker</title>
</head>
<body>
<div id="app">
<div id="#fishes"></div>
</div>
<script src="lib/jquery.js"></script>
<script src="lib/underscore.js"></script>
<script src="lib/backbone.js"></script>
<script src="fishModel.js"></script>
<script src="pondView.js"></script>
<script type="text/javascript">
var goldfish = new Fish({
name: 'Goldfish',
image: 'http://tinyurl.com/n4vgcl5'
});
var fugu = new Fish({
name: 'Pufferfish',
image: 'http://tinyurl.com/kxd7cuu'
});
var tuna = new Fish({
name: 'Tuna',
image: 'http://tinyurl.com/kxd7cuu'
});
var myPond = new Backbone.Collection([goldfish, fugu, tuna], {model: Fish});
var pondView = new PondView({collection: myPond});
</script>
</body>
</html>
var Fish = Backbone.Model.extend({
defaults: {
name: "Larry",
image: 'http://www.google.com'
}
});
var PondView = Backbone.View.extend({
el: "#app",
tagName: 'table',
initialize: function() {
this.listenTo(this.collection, "change:name", this.render);
},
render: function() {
$('#fishes').html('');
this.collection.each(function(fish) {
$('#fishes').append('<tr><td><%=' + fish.get("name") + '%> < /td><td><img src ="' + fish.get('image') + "/>< /td></tr >")
})
}
});
You didn't render your view.
Add after view creation:
var Fish = Backbone.Model.extend({
defaults: {
name: "Larry",
image: 'http://www.google.com'
}
});
var PondView = Backbone.View.extend({
el: "#app",
tagName: 'table',
initialize: function() {
this.listenTo(this.collection, "change:name", this.render);
},
render: function() {
this.$el.html('');
this.collection.each(function(fish) {
this.$el.append('<tr><td>' + fish.get("name") + ' </td><td><img src="' + fish.get('image') + '" /></td></tr>')
}.bind(this))
}
});
var goldfish = new Fish({
name: 'Goldfish',
image: 'http://tinyurl.com/n4vgcl5'
});
var fugu = new Fish({
name: 'Pufferfish',
image: 'http://tinyurl.com/kxd7cuu'
});
var tuna = new Fish({
name: 'Tuna',
image: 'http://tinyurl.com/kxd7cuu'
});
var myPond = new Backbone.Collection([goldfish, fugu, tuna], {model: Fish});
var pondView = new PondView({collection: myPond});
pondView.render()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script src="http://backbonejs.org/backbone.js"></script>
<div id="app">
<div id="#fishes"></div>
</div>
I have the following backbone application:
On the index.html:
<div class='content'></div>
<div class='container'>
<script type="type="text/x-handlebars-template"" id="product-template">
<h2>Products</h2>
<h3>{{ this.title }}</h3>
</script>
</div>
and the main.js:
$(function() {
var Product = Backbone.Model.extend({
defaults: {
title: "Title",
user_id: 0,
description: "Description"
}
});
var ProductView = Backbone.View.extend({
el: ".content",
initialize: function() {
this.render();
},
render: function() {
var source = $('#product-template').html();
var template = Handlebars.compile(source);
var html = template(Product.model);
this.$el.html(html);
}
});
var productView = new ProductView();
});
It's showing the "Products" heading, so the template is rendering but it's not showing the {{this.title }}. Unfortunately, there isn't any errors showing up in the console, either.
try this:
var ProductView = Backbone.View.extend({
el: ".content",
model: new Product,
initialize: function() {
this.render();
},
render: function() {
var source = $('#product-template').html();
var template = Handlebars.compile(source);
var html = template(this.model.toJSON());
this.$el.html(html);
}
});
to print it
{{ title }}
I have problem with my groupedBy collections because is not rendered after second event click. I think there is problem with fetch my collection...but I don't know how it fix. There is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Backbone test</title>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
ul.items{list-style: none;width: 100%;margin: 0px;-webkit-margin-before: 0em;-webkit-padding-start: 0px;}
</style>
</head>
<body>
<header>
</header>
<content id="content">
<div id="persons"></div>
<div id="items"></div>
<div id="orders"></div>
</content>
<footer>
</footer>
<script id="itemsTemlate" type="text/template">
<div class="jumbotron">
<div class="container">
<h1>My Items!</h1>
</div>
<button class="open-orders" style="float:left;">Orders</button>
<button class="open-persons" style="float:right;">Persons</button>
</div>
<% _.each( data, function( category, i ){ %>
<h3 class="category-name"><%= i %></h3>
<div><% _.each( category, function( item ){ %>
<li class="product"><%= item.title %><p style="float:right;" class="cccc">-</p><p style="float:right;" class="cccc">+</p></li>
<% }) %>
</div>
<% }) %>
</script>
<script id="ordersTemlate" type="text/template">
<div class="jumbotron">
<div class="container">
<h1>My Orders!</h1>
</div>
<button class="open-items" style="float:left;">Items</button>
<button class="open-persons" style="float:right;">Persons</button>
</div>
<% _.each( data, function( category, i ){ %>
<h3 class="category-name"><%= i %></h3>
<div><% _.each( category, function( order ){ %>
<li class="order"><%= order.title %><p style="float:right;" class="cccc">X</p></li>
<% }) %>
</div>
<% }) %>
</script>
<script id="personsTemlate" type="text/template">
<div class="jumbotron">
<div class="container">
<h1>My Persons!</h1>
</div>
<button class="open-items" style="float:left;">Items</button>
<button class="open-orders" style="float:right;">Orders</button>
</div>
<% _.each( data, function( category, i ){ %>
<h3 class="category-name"><%= i %></h3>
<div><% _.each( category, function( person ){ %>
<li class="product"><%= person.title %><p style="float:right;" class="cccc">X</p></li>
<% }) %>
</div>
<% }) %>
</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.1/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script>
(function() {
window.App = {
Models: {},
Collections: {},
Views: {},
Router: {}
};
window.vent = _.extend({}, Backbone.Events);
})();
// !models.js
App.Models.Item = Backbone.Model.extend({});
App.Models.Person = Backbone.Model.extend({});
App.Models.Order = Backbone.Model.extend({});
// !collections.js
App.Collections.Items = Backbone.Collection.extend({
model: App.Models.Item,
url: 'api/items.json'
});
App.Collections.Persons = Backbone.Collection.extend({
model: App.Models.Person,
url: 'api/persons.json'
});
App.Collections.Orders = Backbone.Collection.extend({
model: App.Models.Order,
url: 'api/orders.json'
});
// !views.js
App.Views.Items = Backbone.View.extend({
el: '#items',
events: {
'click button.open-orders':'openOrders',
'click button.open-persons':'openPersons',
},
openOrders: function() {
this.remove();
this.unbind();
App.myRouter.navigate("orders", {trigger: true, replace: true});
console.log("openOrders");
},
openPersons: function() {
this.remove();
this.unbind();
App.myRouter.navigate("persons", {trigger: true, replace: true});
console.log("openPersons");
},
initialize: function() {
this.listenTo( this.collection, "change", this.render );
this.template = _.template( document.getElementById('itemsTemlate').innerHTML );
this.render();
this.$el;
},
getGroups : function(){
return _.groupBy(this.collection.toJSON(), 'category');
},
render: function() {
this.el.innerHTML = this.template({ data : this.getGroups() });
},
});
App.Views.Persons = Backbone.View.extend({
el: '#persons',
events: {
'click button.open-items':'openItems',
'click button.open-orders':'openOrders',
},
openItems: function() {
this.remove();
this.unbind();
App.myRouter.navigate("items", {trigger: true, replace: true});
},
openOrders: function() {
this.remove();
this.unbind();
App.myRouter.navigate("orders", {trigger: true, replace: true});
},
initialize: function() {
this.listenTo( this.collection, "change", this.render );
this.template = _.template( document.getElementById('personsTemlate').innerHTML );
this.render();
this.$el;
},
getGroups : function(){
return _.groupBy(this.collection.toJSON(), 'category');
},
render: function() {
this.el.innerHTML = this.template({ data : this.getGroups() });
},
});
App.Views.Orders = Backbone.View.extend({
el: '#orders',
events: {
'click button.open-items':'openItems',
'click button.open-persons':'openPersons',
},
openItems: function() {
this.remove();
this.unbind();
App.myRouter.navigate("items", {trigger: true, replace: true});
},
openPersons: function() {
this.remove();
this.unbind();
App.myRouter.navigate("persons", {trigger: true, replace: true});
},
initialize: function() {
this.listenTo( this.collection, "change", this.render );
this.template = _.template( document.getElementById('ordersTemlate').innerHTML );
this.render();
this.$el;
},
getGroups : function(){
return _.groupBy(this.collection.toJSON(), 'category');
},
render: function() {
this.el.innerHTML = this.template({ data : this.getGroups() });
},
});
// !router.js
App.Router = Backbone.Router.extend({
routes: {
'':'persons',
'persons':'persons',
'items':'items',
'orders':'orders'
},
persons: function() {
App.persons = new App.Collections.Persons;
App.persons.fetch().then(function() {
new App.Views.Persons({ collection: App.persons });
});
console.log('persons page !');
},
items: function() {
App.items = new App.Collections.Items;
App.items.fetch().then(function() {
new App.Views.Items({ collection: App.items });
});
console.log('items page !');
},
orders: function() {
App.orders = new App.Collections.Orders;
App.orders.fetch().then(function() {
new App.Views.Orders({ collection: App.orders });
});
console.log('orders page !');
},
});
App.myRouter = new App.Router();
Backbone.history.start();
</script>
</body>
</html>
Sounds like you could use an itemView. This is when marionette comes in very handy.
check out marionette
I have next problem with function each. I wanna render all tables from collection, after that add function for create new table. But I don't know why I have in console error:
Uncaught TypeError: Cannot call method 'each' of undefined
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Backbone test</title>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<header>
<div class="jumbotron">
<div class="container">
<h1>My tables!</h1>
</div>
</div>
</header>
<content>
<div id="add-table">
<div class="container">
<label>Add new table!</label>
<form>
<legend>Name</legend>
<div class="input-group">
<span class="input-group-btn">
<button class="btn btn-default" type="button">Go!</button>
</span>
<input type="text" class="form-control">
</div>
</form>
</div>
</div>
<div id="content"></div>
</content>
<script id="allTableTemlate" type="text/template">
<li><%= name %></li>
</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.1/underscore-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script>
// !main.js
(function() {
window.App = {
Models: {},
Collections: {},
Views: {},
Router: {}
};
window.vent = _.extend({}, Backbone.Events);
window.template = function(id) {
return _.template( $('#' + id).html() );
};
})();
// !models.js
App.Models.Table = Backbone.Model.extend({});
// !collections.js
App.Collections.Tables = Backbone.Collection.extend({
model: App.Models.Table,
url: 'tables.json'
});
// !views.js
App.Views.App = Backbone.View.extend({
initialize: function() {
var allTablesView = new App.Views.Tables({ collection: App.tables }).render();
$(document.body).append(allTablesView.el);
}
});
App.Views.Tables = Backbone.View.extend({
tagName: 'ul',
render: function() {
this.collection.each( this.addOne, this );
return this;
},
addOne: function(table) {
var tableView = new App.Views.Tables({ model: table });
this.$el.append(tableView.render().el);
},
});
App.Views.Table = Backbone.View.extend({
tagName: 'li',
template: template('allTableTemlate'),
render: function() {
this.$el.html( this.template( this.model.toJSON() ) );
return this;
},
});
// !router.js
App.Router = Backbone.Router.extend({
routes: {
'':'index',
},
index: function() {
console.log('index page !');
},
});
// !index.html
new App.Router;
Backbone.history.start();
App.tables = new App.Collections.Tables;
App.tables.fetch().then(function() {
new App.Views.App({ collection: App.tables });
});
</script>
</body>
</html>
This is my complete code with json data :
[
{"name": "Table 1","stts": "redstts","id": 1},
{"name": "Table 2","stts": "redstts","id": 2},
{"name": "Table 3","stts": "redstts","id": 3},
{"name": "Table 4","stts": "redstts","id": 4},
{"name": "Table 5","stts": "redstts","id": 5}
]
There is a typo in your addOne function. You should be creating a new "App.Views.Table" instead of "new App.Views.Tables" :
addOne: function(table) {
var tableView = new App.Views.Table({ model: table });
this.$el.append(tableView.render().el);
}