I encountered the following error:
Uncaught TypeError: Cannot call method 'compile' of undefined.
RequireJS configuration:
requirejs.config({
baseUrl: "resources",
paths: {
'app':'lib',
'jquery': 'lib/jquery-1.9.1',
'bootstrap': 'lib/bootstrap',
'html5shiv': 'lib/html5shiv',
'spin': 'lib/spin',
'respond': 'lib/respond',
'underscore': 'lib/underscore',
'backbone': 'lib/backbone',
'handlebars': 'lib/handlebars-v3.0.3',
'template': 'app/templates'
},
shim: {
html5shiv: {
deps: ['jquery']
},
respond: {
deps: ['jquery']
},
bootstrap: {
deps: ['jquery']
},
jquery: {
exports: '$'
},
underscore: {
exports: '_'
},
backbone: {
deps: ['jquery', 'underscore'],
exports: 'Backbone'
},
handlebars: {
exports: "Handlebars"
}
}
});
require([
'jquery',
'underscore',
'backbone',
'handlebars',
'app/Router'
], function($,
_,
Backbone,
Handlebars,
Router) {
var router = new Router();
Backbone.history.start();
});
View:
define([
'backbone',
'handlebars',
'text!templates/mytemplate.html'
], function(Backbone, Handlebars, Template){
MyView = Backbone.View.extend({
tagName: 'li',
template: Handlebars.compile(Template),
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
}
});
return MyView;
});
shim is for libraries that doesn't support AMD. The version of handlebars you're using probably supports AMD and doesn't define a global variable named Handlebars. Hence you get the error. Try removing handlebars config from shim.
Related
I have the following directory structure to my tpl:
-src
-assets
-js
-lib
[files]
-src
-templates
-common
builder_regions.tpl
My require.config is:
require.config({
baseUrl:'src/assets/js',
paths: {
backbone: 'lib/backbone',
jquery: 'lib/jquery.min',
'jquery-ui': 'lib/jquery-ui-1.10.4.custom.min',
underscore: 'lib/underscore.min',
modernizr: 'lib/modernizr.min',
'magnific-popup': 'lib/magnific-popup.min',
text: 'src/assets/jslib/text',
marionette: 'lib/backbone.marionette.min',
tpl: 'lib/underscore-tpl'
},
shim: {
jquery: {
exports: '$'
},
underscore: {
exports: '_'
},
backbone: {
deps: [ 'jquery', 'underscore' ],
exports: 'Backbone'
},
marionette: {
deps: [ 'jquery', 'underscore', 'backbone' ],
exports: 'Marionette'
},
'jquery-ui': {
deps: [ 'jquery' ],
exports: '$ui'
},
'magnific-popup': {
deps: [ 'jquery' ],
exports: 'magnificPopup'
},
tpl: [ 'text' ]
}
});
My require module is set-up as:
define([ 'tpl!src/templates/common/builder_regions.tpl', function( Marionette, layoutTpl ) {
console.log( 'did not throw' );
});
When I access the module I get the following error:
GET http://localhost:3000/src/assets/js/src/tpl.js 404 (Not Found)
Why is file tpl.js being referenced when I provided the path in require.config? Thanks!
If your underscore-tpl.js is this one then you do not need a shim configuration for it because it calls define by itself. If you use a shim configuration for something that does not need a shim, RequireJS can behave strangely.
Another thing not related to the problem you are reporting here but could give you trouble down the line: jQuery has not needed a shim since at least version 1.9. So if you use a version that is >= 1.9, you should remove the shim you have for jquery.
Try This:
define(['marionette', 'tpl!src/templates/common/builder_regions.tpl'], function( Marionette, layoutTpl ) {
console.log( 'did not throw' );
});
I have the following main.js
requirejs.config({
baseUrl: 'js',
paths: {
"jquery": "http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"
},
shim: {
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'marionette': {
deps: ['jquery', 'underscore', 'backbone'],
exports: 'Marionette'
},
'underscore': {
exports: '_'
}
}
});
The code to require query:
define(['jquery', 'backbone', 'marionette'], function($, Backbone, Marionette) {
Backbone, marionette and underscore all load correctly, but requireJS is ignoring the 'paths' config and trying to load jquery from js/jquery.js, not the CDN.
Using requires 2.1.9
You should exclude the ".js" extension from the CDN URL, just as you would for file paths in your baseUrl directory:
paths: {
"jquery": "http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min"
},
I am a newbie with backbone.js and require.js, I still not clear of how to use require.js. Now I'm trying to use require.js with Jquery Reveal.
This is my main.js :
requirejs.config({
enforceDefine: true,
paths: {
"jquery": "libs/jquery/jquery-min",
"underscore": "libs/underscore/underscore-min",
"backbone": "libs/backbone/backbone-min",
"jquery.reveal":"libs/jquery/jquery.reveal"
},
shim: {
"underscore": {
deps: [],
exports: "_"
},
"backbone": {
deps: ["jquery", "underscore"],
exports: "Backbone"
},
"jquery.reveal": ["jquery"]
}
});
define(["jquery", "underscore", "backbone","jquery.reveal"],
function ($, _, Backbone,Jquery_Reveal) {
console.log("reveal " + typeof Jquery_Reveal);
}
);
app.js :
define([
'jquery',
'underscore',
'backbone',
'router',
'jquery.reveal'
], function($, _, Backbone,Router,Reveal){
var initialize = function(){
Router.initialize();
};
return {
initialize: initialize
};
});
Then I got an error in chrome console : Uncaught Error: No define call for reveal.
This is what I found and it works for me:
"reveal": {
deps: ["jquery"],
exports: "jQuery.fn.reveal"
}
I am trying to use the backbone-ui library but cannot figure out the require.js configuration to get the modules loaded.
main.js:
requirejs.config({
baseUrl: '/static/js/facebook_report_app/js',
paths: {
backbone: 'lib/backbone'
, underscore: 'lib/underscore'
, jquery: 'lib/jquery'
, laconic: 'lib/laconic'
, moment: 'lib/moment'
, backboneUI: 'lib/backbone-ui/js/backbone_ui'
, menuUI: 'lib/backbone-ui/js/menu'
, textUI: 'lib/backbone-ui/js/text_field'
, text: 'lib/text'
},
shim: {
'lib/underscore': {
exports: '_'
},
'laconic': {
deps: ["jquery"],
exports: "$.el"
},
'lib/backbone': {
deps: ['lib/underscore']
, exports: 'Backbone'
},
'backboneUI': {
deps: ['lib/backbone', 'laconic', 'jquery']
, exports: 'Backbone.UI'
},
'textUI': {
deps: ['jquery', 'lib/backbone', 'backboneUI', 'laconic']
, exports: 'Backbone.UI.TextField'
},
'menuUI': {
deps: ['lib/backbone', 'backboneUI', 'laconic', 'textUI']
, exports: 'Backbone.UI.Menu'
},
'lib/backgrid': {
deps: ['lib/underscore', 'lib/backbone']
, exports: 'Backgrid'
},
'report_app': {
deps: ['lib/underscore', 'lib/backbone', 'lib/backgrid', 'backboneUI']
}
}
});
require([
'facebook_report_app'
],
function(FacebookReportApp) {
window.fbReport = new FacebookReportApp();
});
menu_user.js
define(['jquery', 'lib/backbone', 'backboneUI', 'menuUI', 'laconic'], function(AccountPickerView) {
var AccountPickerView = Backbone.UI.Menu.extend({
el: '.left-nav',
});
return AccountPickerView;
});
When I load this in dev, the console reports "Object [object Object] has no method 'input' ", on line 44 of the text_field.js of the Backbone-UI library.
I suppose my configuration approach is broken to begin with -- I added the menu.js and text_field.js files bc I was getting errors 'Backbone.UI.Menu' and Backbone.UI.TextField' (a requirement of Menu) weren't defined. But there must be a cleaner way to bring in the various files of backbone-ui.
So how do I get rid of the 'no method input' error? Or better configure to use Backbone UI? Or should I be using jQuery UI in the first place? In which case, where do I go to figure out configuration of that?
I got it working, after much fiddling with the following setup:
js/main.js
requirejs.config({
baseURL: 'js',
urlArgs: "bust=" + (new Date()).getTime(),
shim: {
underscore: {
exports: '_'
},
jquery: {
exports: '$'
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
laconic: {
exports: '$.el'
},
backbone_ui: {
deps: ['underscore', 'jquery', 'backbone', 'laconic', 'moment'],
exports: 'Backbone.UI'
}
},
paths: {
jquery: 'http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min',
moment: './lib/moment.min',
laconic: './lib/laconic',
underscore: 'http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min',
backbone: 'http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min',
backbone_ui: './lib/backbone-ui',
crypto: 'http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/md5',
templates: '../templates',
collections: './collections',
models: './models',
}
});
js/views/json.js
define(['jquery','underscore', 'backbone', 'backbone_ui'],
function($,_,Backbone, BBUI){
var JsonView = Backbone.View.extend({
className: "json-item",
initialize: function(data){
var self = this;
this.app = data.app;
this.model = data.model;
this.listenTo(this.model, "change", function(){
console.log("model changed", self.model);
});
this.model.fetch({
success: function(){
self.render();
}
});
},
render: function(){
var self = this;
$(this.el).empty();
for (key in this.model.attributes){
this.el.appendChild(new Backbone.UI.Label({content:key}).render().el);
this.el.appendChild(new Backbone.UI.TextField({model: this.model, content:key}).render().el);
}
this.el.appendChild(new Backbone.UI.Button({content:"save", onClick: function(){self.model.save()}}).render().el);
return this;
}
});
return JsonView;
});
Please note that I import backbone-ui as BBUI and never reference it that way. BBUI.TextField() is a defined function and using it would work as well, but the way Backbone-ui is set up it makes alterations to Backbone, Jquery, and Underscore when it loads. So I figured I just needed it to be run prior to the view getting loaded.
I have an underscore JS template and a jQuery plug-in that depends on the markup that gets rendered after the template is visible, but the problem is when I use jQuery document ready, it doesn't get the HTML that is rendered.
I used domReady but still ain't working, how can I accomplish this probably? This is what I got so far:
main.js
requirejs.config({
baseUrl: 'js/modules',
shim: {
// 'jquery.colorize': ['jquery'],
// 'jquery.scroll': {
// deps: ['jquery'],
// exports: 'jQuery.fn.colorize'
// },
'backbone': {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'underscore': {
deps: ['jquery'],
exports: '_'
}
},
paths: {
'jquery': '../libs/jquery',
'underscore': '../libs/underscore',
'backbone': '../libs/backbone',
'text': '../libs/text',
'views': '../views',
'templates': '../../templates',
'domReady': '../libs/domReady',
'ui': '../ui'
}
});
requirejs(['homeView', 'ui/placeholder'], function(Main){
Main.initialize();
});
homeView.js
define(['jquery', 'underscore', 'backbone', 'text!templates/home.html'], function($, _, Backbone, homeTemplate){
var HomeView = Backbone.View.extend({
el: $("#application"),
events: function(){
// Empty.
},
initialize: function(){
// Empty.
},
render: function(){
$('body').addClass('pt-dark');
$(this.el).html(_.template(homeTemplate, {}));
}
});
return new HomeView;
});
ui/placeholder.js
requirejs(['domReady', 'jquery'], function(doc, $){
doc(function(){
// Empty should contain the template html at this point.
console.log($('body').html());
});
});
Thanks a lot for help!
Try this:
define(['jquery', 'underscore', 'backbone', 'text!templates/home.html'], function($, _, Backbone, homeTemplate){
var HomeView = Backbone.View.extend({
el: $("#application"),
template: _.template(homeTemplate),
events: function(){
// Empty.
},
initialize: function(){
// Empty.
},
render: function(){
$('body').addClass('pt-dark');
this.$el.html(this.template({})));
jQuery('#the_thing_you_need', this.$el).theFunctionYouNeed();
}
});
return new HomeView;
});
Note that you should define a local attribute to the view called 'template' or something of that sort to store your template in and not re-call _.template every time that you need it.
Also, instead of jQuery(this.el) you can use this.$el.