Backbone: Uncaught ReferenceError: attribute is not defined - backbone.js

I am using gem 'backbone-on-rails' #https://github.com/meleyal/backbone-on-rails and I am trying to create a "new quote" view, with a blank form. Should be very simple. :S But all I get is this error:
Uncaught ReferenceError: description is not defined By debugging the error appears to happen on the View->render method.
This is the code:
Router:
class SpencerGrafica.Routers.Quotes extends Backbone.Router
routes:
'new' : 'newQuote'
newQuote: ->
new SpencerGrafica.Views.NewQuote model: new SpencerGrafica.Models.Quote
View:
class SpencerGrafica.Views.NewQuote extends Backbone.View
el: '#app'
template: JST["quotes/new"]
initialize: ->
#render()
render: ->
$(#el).html(#template(#model.toJSON()))
#
Model
class SpencerGrafica.Models.Quote extends Backbone.Model
defaults:
description: null
Template
<form id="new-quote" name="quote">
<div>
<input type="text" name="description" value="<%= description %>" placeholder="Descripcion interna">
</div>
<div class="actions">
<input type="submit" value="Add Post" />
</div>
</form>
Any help REALLY appreciated. :)

try
class SpencerGrafica.Views.NewQuote extends Backbone.View
el: '#app'
template: JST["quotes/new"]
initialize: ->
#render()
render: => # fat arrow here
$(#el).html(#template(#model.toJSON()))

Related

MarionetteJS - Not able to render the data using toJSON function

I am using HandlebarsJS plugin to render my templates. I am getting error while i call the rendering function.
when i console the this.model.toJSON(), i am getting correct datas, as well I console the "homeEditTemp" I am getting my templates too..
But when i pass my data to template i am getting error as : Uncaught TypeError: undefined is not a function
here is my code :
define([
'jquery',
'underscore',
'backbone',
'marionette',
'hbs!scripts/templates/home/homeEditTemp'],
function ($,_,Backbone, Marionette, homeEditTemp) {
"use strict";
window.socialApp = window.socialApp || {};
socialApp.homeView = Backbone.Marionette.ItemView.extend({
initialize : function (model) {
this.model = model;
},
render : function () {
console.log(this.model.toJSON()) // works fine
console.log(homeEditTemp) // works fine.
this.$el.html(homeEditTemp(this.model.toJSON())); // throws the error..
}
});
return socialApp.homeView;
});
here is my handlebars template :
<form>
<div class="control-group">
<label for="firstName" class="control-label"> First name:</label>
<input id="firstName" name="firstName" type="text" value="{{firstName}}"/>
</div>
<div class="control-group">
<label for="lastName" class="control-label"> Last name:</label>
<input id="lastName" name="lastName" type="text" value="{{lastName}}"/>
</div>
<div class="control-group">
<label for="email" class="control-label">Phone number:</label>
<input id="email" name="email" type="text" value="{{email}}"/>
</div>
<button class="btn js-submit">Save</button>
</form>
Thanks in advance!
update :
when i manually assign the value, it works fine like this:
render : function (model) {
var obj = {
"firstName" : "testFirstName ",
"lastName" : " test lastName"
}
this.$el.html(homeEditTemp(obj));
}
what would be the issue?
when i console my model it show like this:
Object {model: s}model: s_changing: false_events: Object_pending: false_previousAttributes: Objectattributes: Objectchanged: Objectcid: "c6"__proto__: n__proto__: Object
At first you need to compile your template
var tpl = function () {
return Handlebars.compile(homeEditTemp);
}
Then you can use this
this.$el.html(tpl(this.model.toJSON()));
try it like this:
socialApp.homeView = Backbone.Marionette.ItemView.extend({
template:homeEditTemp,
initialize : function (model) {
this.model = model;
},
render : function () {
var output = this.template(this.model.toJSON());
this.$el.html(output);
return this;
}
});
but #vahan is right and you don't need to overwrite the render method usually, just have the template and model variable set and marionette will take care of it
I changed the model - implementation like this, it works for me.
initialize : function (arg) {
this.model = arg.model; //it works!
}
instead of :
initialize : function (model) {
this.model = model; //i am not directly got the model here..?
}

Backbone Marionette events, Zurb Foundation's Reveal Modals

I'm building a modal popup by jamming a Backbone Marionette itemview into a Foundation Reveal modal. The modals appear but no events fire. Specifically, I'm trying to catch a click event.
I load Foundation from a Marionette Layout view.
'use strict';
define([
'jquery',
'underscore',
'backbone',
'region/actionbar',
'region/modal',
'text!/js/template/global.ejs',
'js/views/actionbar/actionbar.js',
'less!/style/global.less',
'css!/js/bower_components/foundation/css/foundation.css',
'/js/bower_components/foundation/js/foundation/foundation.js',
'/js/bower_components/foundation/js/foundation/foundation.reveal.js',
'marionette'
], function ($, _, Backbone, ActionBar, Modal, Template, ActionBarView) {
var GlobalLayout = Backbone.Marionette.Layout.extend({
template: _.template(Template),
el: 'body',
regions: {
content: "#content",
actionBar: ActionBar,
modal: '#modal'
},
initialize: function(){
},
onRender: function(){
// Load foundation
$(document).foundation();
},
title: function(title) {
// this.actionbar.title(title);
// document.title = "Workbench :: " + title;
}
});
var layout = new GlobalLayout();
layout.render();
return layout;
});
The popup is being loaded from a click event in a view in the actionbar region. Here's the Region:
'use strict';
define([
'jquery',
'underscore',
'backbone',
'marionette'
], function ($, _, Backbone) {
var ActionBar = Backbone.Marionette.Region.extend({
el: "#action-bar"
});
return ActionBar;
});
...and here's the View in that region. onSignUp() jams my SignUp modal into the Modal region. It then re-initializes foundation.
'use strict';
define([
'jquery',
'underscore',
'backbone',
'layout/global',
'/js/views/modals/sign-up.js',
'/js/views/modals/sign-in.js',
'model/user',
'text!/js/template/actionbar/actionbar.ejs',
'less!/style/global.less',
'marionette'
], function ($, _, Backbone, layout, SignUp_Modal, SignIn_Modal, User, Template) {
var ActionBarView = Backbone.Marionette.ItemView.extend({
initialize: function(){
this.setElement('#action-bar');
},
template: _.template(Template),
events: {
"click .sign-in" : "onSignIn",
"click .sign-up" : "onSignUp"
},
onSignUp: function(e){
// e.preventDefault();
layout.modal.show( new SignUp_Modal() );
$(document).foundation();
},
onSignIn: function(e){
// Prevent the link from doing anything.
e.preventDefault();
// Load modal popup that requests user to sign in
layout.modal.show( new SignIn_Modal() );
$(document).foundation();
}
});
return ActionBarView;
});
Finally, here's my SignUp_Modal view and its template.
'use strict';
define([
'jquery',
'underscore',
'model/user',
'text!/js/template/modals/sign-up.ejs',
'marionette'
], function ( $, _, User, Template){
var Modal = Backbone.Marionette.ItemView.extend({
events: {
'click #join': 'onJoin',
'click .me': 'onJoin'
},
template: _.template(Template),
onJoin: function(e){
// Check whether the click events do anything
console.log('Heard it');
}
});
return Modal;
});
Template:
<div id="signUp" class="reveal-modal" data-reveal>
<form>
<div class="row">
<div class="small-8">
<div class="row">
<div class="small-3 columns">
<label for="email" class="right inline">Email</label>
</div>
<div class="small-9 columns">
<input type="text" id="email" placeholder="Email">
</div>
</div>
<div class="row">
<div class="small-3 columns">
<label for="phone" class="right inline">Phone</label>
</div>
<div class="small-9 columns">
<input type="text" id="phone" placeholder="Phone">
</div>
</div>
<div class="row">
<div class="small-3 columns">
<label for="pass" class="right inline">Password</label>
</div>
<div class="small-9 columns">
<input type="password" id="pass">
</div>
</div>
<div class="row">
<label>Username will be...</label>
<input type="radio" name="username" value="email" id="username_email" checked><label for="username_email">Email</label>
<input type="radio" name="username" value="phone" id="username_phone"><label for="username_phone">Phone</label>
</div>
<div class="row">
<div class="small-3 columns">
Join
</div>
</div>
</div>
</div>
</form>
<div class="me">blaaaa</div>
<a class="close-reveal-modal">×</a>
</div>
I'm betting any of these would be helpful:
Boilerplate example showing how to implement Zurb Foundation with a backbone project, specifically where you're jamming a backbone view into a foundation modal?
Any general reasons why views don't hear click events?
Have I improperly loaded the view into the region?
The error occurs specifically when I click either the element with class="me" or id="join". Both of these should call onJoin() but neither do.
The events are not being trigger because foundation creates a new DOM element to hold the modal, this element is outside of your ItemView's instance's el, and as you might know Backbone only delegate events to the element associated with the view.

rendering template html via backbone view

I have a simple page that contains a 3 step wizard. Basically, the user fills out a textbox, clicks next, which loads the next form field.
I have setup all the HTML inside a template and use that template in a backbone view.
The problem is, backbone isn't rendering the HTML inside the template. I just get a blank screen.
Here is my template:
<script type="text/template" id="assessmentTitleTemplate">
<div id="titleDiv">
<label for="title">Title:</label> <input type="text" />
</div>
<div id="choicesDiv" style="display: none;">
<label for="choices">Choices:</label><input type="text" />
</div>
<div id="typeDiv" style="display: none;">
<label for="types">Types:</label>
<select name="type">
<option>red</option>
<option>blue</option>
<option>green</option>
</select>
</div>
<div id="directionControl">
<input type="button" value="Prev" /> <input type="button" value="Next" />
</div>
</script>
This is my backbone javascript code:
"use strict";
var titleView = Backbone.View.extend({
tagName: 'div',
className: 'title',
template: _.template($('#assessmentTitleTemplate').html()),
events: {
'click .next': 'saveProceedNext',
'click .prev': 'ProceedPrev'
},
initialize: function () {
this.render;
},
render: function () {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
saveProceedNext: function() {
this.$('#titleDiv').hide();
this.$('#choicesDiv').show();
},
ProceedPrev: function() {
}
});
Your code is correct, but you're missing a couple of parens in your initialize body:
initialize : function () {
this.render(); // it was this.render; before
}
Your code isn't invoking the function.
Also, you're missing class tags for your buttons, or else they won't work when clicked. Adding this will make them work:
<input type="button" value="Prev" class="prev" /> <input type="button" value="Next" class="next" />
Check this JSFiddle.

BackboneJs Multiple Template rendering for a single view when edit vs list

I am developing my first backbone application and i have the following app.js code:
https://gist.github.com/mikedevita/f26cb481385c5574001e
and the following view templates:
<button id="addZone" class="btn btn-success">Add Zone</button>
<script type="text/template" id="zone-template">
<td>(<%= id %>) <%= name %></td>
<td><i class="icon-edit" title="Edit"></i> | <i class="icon-trash" title="Delete"></i></td>
</script>
<script type="text/template" id="zoneEdit-template">
<td>
<form method="POST" class="form-inline" id="edit-form">
<input type="text" name="name" value="<%= name %>" class="input-small">
<input type="submit" class="btn btn-small btn-primary" title="Submit"><i class="icon-check"></i></input>
</form>
</td>
<td><i class="icon-trash" title="Delete"></i></td>
</script>
How can i render the edit template for when editing a "zone" and fire off the list template (default) when the edit is finished.
It works great right now to render the edit template when you click the edit icon, but i cant figure out how to get it to fire the list template on change event of the model.
I have a full working setup of the app on my c9 account:
https://c9.io/gorelative/backbone-test
After reviewing your code, it turns out it was just a missing call to a function. You were declaring this.render in the model.change callback instead of properly calling the function this.render();
App.Views.Zone = Backbone.View.extend({
//...
initialize: function(){
this.template = _.template( $('#zone-template').html() );
this.model.on('change', function(){
this.template = _.template( $('#zone-template').html() );
this.render(); /* you were not calling */
}, this);
this.model.on('destroy', this.remove, this);
},
//...
});

backbone.js event listeners can only be attached to child elements of the "el" property

I am following the backbone tutorial http://backbonetutorials.com/what-is-a-view/ and in the paragraph Listening for events there is the following phrase:
Remember that event listeners can only be attached to child elements of the "el" property.
and then they are doing the following code:
<script type="text/template" id="search_template">
<label>Search</label>
<input type="text" id="search_input" />
<input type="button" id="search_button" value="Search" />
</script>
<div id="search_container"></div>
<script type="text/javascript">
SearchView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function(){
var template = _.template( $("#search_template").html(), {} );
this.$el.html( template );
},
events: {
"click input[type=button]": "doSearch"
},
doSearch: function( event ){
// Button clicked, you can access the element that was clicked with event.currentTarget
alert( "Search for " + $("#search_input").val() );
}
});
var search_view = new SearchView({ el: $("#search_container") });
</script>
But the el property is #search _container which does not have children at all. And they are applying the listener to the input which is the child of search_template
I think I misunderstood something, because it does not make any sense for me. Can anyone right me?
When SearchView.render is called #search _container will have children , the content of the template defined in #search_template
In backbone.js events are delegated, in fact we don't care the HTML is not yet rendered because events will automatically be attached when the view is rendered.

Resources