Backbone / ReactJS view not recognizing JSX - backbone.js

I'm starting on a Backbone AMD application, using React.js for the views. The view is not recognizing the JSX I've written in the render() function. Am I missing a statement in the router or view? The error I'm receiving is 'Unexpected token <'.
Below is the app flow from top to bottom:
Index.html
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<!--<script src="http://fb.me/react-0.12.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.0.js"></script> -->
<script data-main="js/main" src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.15/require.min.js"></script>
main.js
require.config({
paths: {
jquery: 'http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min',
underscore: 'http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min',
backbone: 'http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min',
react: 'http://fb.me/react-0.12.0',
JSXTransformer: 'http://fb.me/JSXTransformer-0.12.0'
}
});
require([
// Load our app module and pass it to our definition function
'app',
], function(App){
// The "app" dependency is passed in as "App"
App.initialize();
});
app.js
define([
'jquery',
'underscore',
'backbone',
'router' // Request router.js
], function($, _, Backbone, Router){
var initialize = function(){
// Pass in our Router module and call it's initialize function
Router.initialize();
}
return {
initialize: initialize
};
});
router.js
define([
'jquery',
'underscore',
'backbone',
'views/team/list'
], function($, _, Backbone, TeamListView){
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'team': 'showTeam',
// Default
'*actions': 'defaultAction'
}
});
var initialize = function(){
var app_router = new AppRouter;
app_router.on('route:showTeam', function(){
// Call render on the module we loaded in via the dependency array
// 'views/teams/list'
var teamListView = new TeamListView();
teamListView.render();
});
app_router.on('route:defaultAction', function(actions){
// We have no matching route, lets just log what the URL was
console.log('No route:', actions);
});
Backbone.history.start();
};
return {
initialize: initialize
};
});
list.js
/**
* #jsx React.DOM
*/
define(
[
'jquery',
'underscore',
'backbone',
'react',
'JSXTransformer'
], function($, _, Backbone, react, JSXTransformer){
var MyWidget = React.createClass({
handleClick: function() {
alert('Hello!');
},
render: function() {
return (
<a href="#" onClick={this.handleClick}>Do something!</a>
);
}
}),
var TeamListView = Backbone.View.extend({
el: 'body',
template: '<div class="widget-container"></div>',
render: function() {
this.$el.html(this.template);
React.renderComponent(new MyWidget(), this.$('.widget-container').get(0));
return this;
}
});
// Our module now returns our view
return TeamListView;
});
list.js (updated - working version)
define(
[
'jquery',
'underscore',
'backbone',
'react'
], function($, _, Backbone, React){
var MyWidget = React.createClass({displayName: 'MyWidget',
handleClick: function() {
alert('Hello!');
},
render: function() {
return (<div>
<ul>
<li></li>
<li></li>
</ul>
<div>Test</div>
<a href="#" onClick={this.handleClick}>Do something!</a>
</div>
)
}
});
var TeamListView = Backbone.View.extend({
el: $('#mainContent'),
events: {
},
initialize: function() {
console.log('test');
},
render: function (){
React.render(
React.createElement(MyWidget, null),
document.getElementById('mainContent')
);
}
});
return TeamListView;
});

JSX must be compiled to JavaScript before browsers can understand it.
You can use the jsx tool to do this.
JSX transformer and Require.js are incompatible.

If you're using RequireJS, you can use a JSX plugin like this one. For what it's worth, when I integrated the JSX transformer into our RequireJS setup, it required quite a bit of tweaking and experimentation.

Related

using underscore templates with Backbone and Require.js

I'm trying to create a simple app using underscore templates and backbone (as described in this article). I'm sure that the template file is being loaded correctly, but I'm not so sure whether I'm applying the model to the template properly. (See below example)
I have also checked the output of compiledTemplate variable, but it only contains the <h1> </h1> tags, so it looks like there may be something wrong with the format of my model. But I have not been able to come up witjh any solution so far hence I'm posting this here hoping that someone could possibly help me out with this ..
index.html
<head>
<script src="./dev_env/app/libs/vendor/require.min.js" data-main="dev_env/app/main"></script>
<script>
require(['app_init']);
</script>
</head>
<body >
<div id="test">
</div>
</body>
</html>
./templates/template.html
<h1> <%= obj.title %> </h1>
./app_init.js
require([ '../app' ], function(App){
App.initialize();
});
./app.js
define([ 'backbone', './router', 'underscore','jquery'], function (Backbone, Router, _, $) {
var initialize = function(){
Router.initialize();
}
return {
initialize: initialize
};
});
./models/model_menu.js
define([ 'underscore', 'backbone' ], function(_, Backbone){
var MenuModel = Backbone.Model.extend({
defaults: {
title: "Test1"
}
});
return MenuModel;
});
./collections/collection_menu.js
define([ 'underscore', 'backbone', 'models/model_menu'
], function(_, Backbone, MenuModel){
var MenuCollection = Backbone.Collection.extend({
model: MenuModel
});
return MenuCollection;
});
./router.js
define(['jquery','underscore', 'backbone', 'views/menu/view_menu'], function ($, _, Backbone, vMenu) {
var AppRouter = Backbone.Router.extend({
routes : {
'menu' : 'showMenu',
}
});
var initialize = function () {
var app_router = new AppRouter;
app_router.on('route:showMenu', function () {
var MyMenu = new vMenu();
MyMenu.render();
});
Backbone.history.start();
};
return {
initialize : initialize
};
});
./views/menu_view/view_menu.js
define([ 'jquery','underscore', 'backbone', 'collections/collection_menu', 'text!templates/template.html' ], function ($, _, Backbone, MenuCollection, myTempl) {
var MenuViiew = Backbone.View.extend({
el : $('#test'),
initialize : function () {
this.collection = new MenuCollection();
this.collection.add( {title: "Title2"});
var compiledTemplate = _.template( myTempl, { obj : this.collection.models} );
this.$el.html(compiledTemplate);
}
});
return MenuViiew;
});
I now understand where I was wrong, I misunderstand what a collection was therefore I couldn't make it work. Apologies for that, but I'm still learning this stuff.
here's the solution:
btw. I have changed the collection_menu to menu_collections so it's clear that the file contains a collection of menu models.
views/view_model.js
define([ 'jquery','underscore', 'backbone', 'collections/menu_collections', 'text!templates/template.html' ], function ($, _, Backbone, MenuCollections, myTempl) {
var MenuViiew = Backbone.View.extend({
el : $('#alex'),
initialize : function () {
this.collection = new MenusCollection()
this.collection.add({ title: "Test1" });
this.collection.add({ title: "Test2" });
},
render: function(){
var compiledTemplate = _.template(myTempl, { menus : this.collection.models});
this.$el.html(compiledTemplate);
}
});
return MenuViiew;
});
./templates/template.html
<% _.each(menus, function(menu) { %>
<h1> <%= menu.get('title') %> </h1>
<% }); %>

Calling view function from another view from autocomplete

I have the following views in my application.
sets.js
define([
'jquery',
'underscore',
'backbone',
'bootstrap',
'jqueryui',
'numberformat',
'text!templates/sets/sets.html'
], function ($, _, Backbone, bootstrap, jqueryui, numberformat, setsTemplate) {
var setsView = Backbone.View.extend({
el: $("#contenido"),
events: {
'keyup table tbody input': 'afterRender'
},
initialize: function (options) {
_.bindAll(this, 'render', 'afterRender');
this.options = options || {};
},
render: function () {
var data = {sets: this.options.sets};
var compiledTemplate = _.template(setsTemplate, data);
this.$el.html(compiledTemplate);
$(".alert").addClass('alert-' + this.options.clase);
var tabs = $("#tabs").tabs();
tabs.find(".ui-tabs-nav").sortable({
axis: "x",
stop: function () {
tabs.tabs("refresh");
}
});
$('#emisor').hide();
this.afterRender();
},
afterRender: function () {
console.log('afterRender');
var ventasView = new VentasView();
ventasView.render();
}
})
return setsView;
});
ventas.js
define([
'jquery',
'underscore',
'backbone',
'bootstrap',
'jqueryui',
'text!templates/cliente/cliente.html',
'models/cliente',
'views/sets/sets'
], function ($, _, Backbone, bootstrap, jqueryui, clienteTemplate, SetsView) {
var clienteView = Backbone.View.extend({
el: $("#cliente"),
initialize: function (options) {
this.options = options || {};
},
render: function () {
$("#cliente").html(clienteTemplate);
$('#rut').autocomplete(
{
source: '/clientes/buscar/',
minLength: 1,
dataType: 'json',
cache: false,
select: function (event, ui) {
$("#rut").val(ui.item.Cliente.rut);
$("#id").val(ui.item.Cliente.id);
$("#razon").val(ui.item.Cliente.razon);
$("#giro").val(ui.item.Cliente.giro);
$("#direccion").val(ui.item.Cliente.direccion);
$("#comuna").val(ui.item.Cliente.comuna);
$("#ciudad").val(ui.item.Cliente.ciudad);
var sets = new SetsView();
sets.afterRender();
return false;
}
}).data("autocomplete")._renderItem = function (ul, item) {
return $("<li></li>").data("item.autocomplete", item).append("<a><strong>" + item.Cliente.rut + "</strong></a>").appendTo(ul);
};
}
});
return clienteView;
});
error
Uncaught TypeError: Object [object Object] has no method 'afterRender'
You are missing a parameter in your function :
function ($, _, Backbone, bootstrap, jqueryui, clienteTemplate, SetsView)
function ($, _, Backbone, bootstrap, jqueryui, clienteTemplate, clienteModel, SetsView)

backbone.js Uncaught TypeError: Cannot read property 'View' of null

When I run my backbone app in NetBeans 7.3.1, the main page displays for a few seconds, maybe 5 or 6, then in NetBeans output I see the following...
Uncaught TypeError: Cannot read property 'View' of null (18:43:36:307 | error, javascript)
at (js/views/HomeView.js:6:28)
at d.execCb (js/libs/require/require.js:27:197)
at o (js/libs/require/require.js:10:471)
at (js/libs/require/require.js:12:184)
at o (js/libs/require/require.js:12:75)
at (js/libs/require/require.js:14:1)
at o (js/libs/require/require.js:12:75)
at l (js/libs/require/require.js:12:336)
at g.finishLoad (js/text.js:10:192)
at g.load (js/text.js:10:354)
at window.undefined.window.navigator.window.document.c.onreadystatechange (js/text.js:7:30)
Uncaught TypeError: Cannot read property 'Model' of null (18:43:36:317 | error, javascript)
at (js/models/Member.js:6:26)
at d.execCb (js/libs/require/require.js:27:197)
at o (js/libs/require/require.js:10:471)
at x (js/libs/require/require.js:15:186)
at m (js/libs/require/require.js:15:207)
at g.completeLoad (js/libs/require/require.js:21:388)
at d.onScriptLoad (js/libs/require/require.js:27:490)
Uncaught Error: Load timeout for modules: text!templates/homeTemplate.html
http://requirejs.org/docs/errors.html#timeout (18:43:38:511 | error, javascript)
at N (js/libs/require/require.js:7:217)
at A (js/libs/require/require.js:16:230)
at (js/libs/require/require.js:16:394)
It looks like RequireJS is failing to load Backbone. Here is main.js...
// Filename: main.js
require.config({
shim: {
underscore: {
exports: '_'
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
},
paths: {
jquery: 'libs/jquery/jquery-min',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-min',
templates: '../templates'
}
});
require([
'app',
], function(App) {
App.initialize();
});
I'm totally spinning my wheels on this. Why is Require not loading Backbone?
#Sushanth--: Edited original post to include HomeView.js
Here is the HomeView.js...
define([
'jquery',
'underscore',
'backbone',
'text!templates/homeTemplate.html'
], function($, _, Backbone, homeTemplate) {
var HomeView = Backbone.View.extend({
el: $("#page"),
initialize: function() {
},
render: function() {
var compiledTemplate = _.template( homeTemplate, {} );
this.$el.html( compiledTemplate );
}
});
return HomeView;
});
#Sushanth--: I'm rendering from the router.js...
// Filename: /js/router.js
define([
'jquery',
'underscore',
'backbone',
'views/HomeView',
'views/MembersView'
], function($, _, Backbone, HomeView, MembersView) {
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'members': 'showMembers',
// Default
'*actions': 'defaultAction'
}
});
var initialize = function(){
//alert('router init');
var app_router = new AppRouter;
app_router.on('route:showMembers', function () {
// Like above, call render but know that this view has nested sub views which
// handle loading and displaying data from the GitHub API
var membersView = new MembersView();
});
app_router.on('route:defaultAction', function (actions) {
// We have no matching route, lets display the home page
var homeView = new HomeView();
homeView.render();
});
// Unlike the above, we don't call render on this view as it will handle
// the render call internally after it loads data. Further more we load it
// outside of an on-route function to have it loaded no matter which page is
// loaded initially.
//var footerView = new FooterView();
//alert('hello from router.js');
//Backbone.history.start({pushState: true, root: "/modular-backbone/"});
//Backbone.history.start({pushState: true});
Backbone.history.start();
};
return {
initialize: initialize
};
});
Added a test alert in main.js, app.initialize...
require(['app'], function(App) {
// THIS ALERT NEVER DISPLAYS!?!?!
alert('inside main.js before app.initialize');
App.initialize();
});
I replaced my Backbone and Underscore js files with the AMD versions and it started working.

Backbone.js view events registered but not firing

Just getting started here and cannot seem to get this very basic thing working. All my elements render as I expect. My events register in firefox in the "events" tab, but none of them seem to fire (click, mouseover, etc). I am using the following.
backbone 0.9.2
underscore 1.4.1
Marionette .10.2
require-jquery (requireJs 2.1.0) (jquery 1.8.2)
Router
define([
'jquery',
'backbone',
'underscore',
'views/TodaysProgramsView',
'collections/ProgramSnippetCollection'],
function($, Backbone, _, TodaysProgramsView, ProgramSnippetCollection){
return Backbone.Router.extend({
initialize:function () {
var programSnippetCollection = new ProgramSnippetCollection([
{title:'underwater basket weaving'},
{title:'How to win friends and influence people and stuff'}
]);
this.mainView = new TodaysProgramsView({
el : $("#todays_programs"),
collection:programSnippetCollection
});
Backbone.history.start();
},
routes:{
'':'home'
},
'home':function () {
this.mainView.render();
}
});
});
Collection View [TodaysProgramsView.js]
define([
'jquery',
'backbone',
'underscore',
'views/ProgramSnippetView'],
function($, Backbone, _, ProgramSnippetView){
return Backbone.Marionette.CollectionView.extend({
events: {
"click" : "clicked"
},
clicked : function(){
alert("parent clicked")
},
itemView : ProgramSnippetView
});
});
Item View [ProgramSnippetView.js]
define([
'jquery',
'backbone',
'underscore',
'text!templates/programSnippet.html'],
function($, Backbone, _, template){
return Backbone.Marionette.ItemView.extend({
events: {
"click" : "courseClicked",
'mouseover' : 'mousedOver'
},
render: function(){
var json = this.model.toJSON();
console.log("RENDERING SNIPPET with data", json);
$(this.el).html( _.template(template, json) );
return this;
},
courseClicked : function(){
alert("you clicked a course, good work");
},
mousedOver : function(){
console.log("Mousin!");
}
});
});
After much frustration and many hours of javascript tweaking, I noticed that there was a div set with a z-index to 2. This was overlaying my target and gobbling up all the events. Sigh.

backbone.layoutmanager and handlebars template engine

I'm using the backbone.layoutmanager project:
https://github.com/tbranyen/backbone.layoutmanager#readme
can some one please post a sample with handlebars template engine?
containing the modified app.js file and an instance view?
i have followed the instructions and i'm a bit confused what should i do in the instance level and the global.
i keep getting the "has no method 'match' err message on my template.
Thanks
Your modified app.js will work with something like this:
define([
"jquery",
"underscore",
"backbone",
"handlebars",
"plugins/backbone.layoutmanager"
],
function($, _, Backbone, Handlebars) {
"use strict";
var JST = window.JST = window.JST || {};
Backbone.LayoutManager.configure({
paths: {
layout: "path/to/layouts/",
template: "path/to/templates/"
},
fetch: function(path) {
path = path + ".html";
if(!JST[path]) {
$.ajax({ url: "/" + path, async: false }).then(function(contents) {
JST[path] = Handlebars.compile(contents);
});
}
return JST[path];
}
// It is not necessary to override render() here.
});
var app = {
// Define global resources here.
};
return _.extend(app, Backbone.Events);
});
An example of a view:
var SampleView = Backbone.View.extend({
template: "path/to/sample/template",
// Override this for fine grained control of the context used by the template.
serialize: function() {
return {
property: 1,
anotherProperty: 2
};
}
// No need to override render() for simple templates.
});
And the template associated with the view:
<div>
<h2>{{property}}</h2>
<h2>{{anotherProperty}}</h2>
</div>

Resources