Open josemadriz opened 10 years ago
I ran into this issue as well. I fixed it with a small code change and upgrade to handlebars 2. I won't have the time to make a proper pull request until next week but you are welcome to check it out.
Thanks @nathanjd :) I'll try that alpha then.. And check what has changed form current version.
see #109. Need to wait before Handlebars 2 final release as stated by @sindresorhus. It is the main reason why I complete work done by @nathanjd + support for partials.
AMD output currently does not work with handlebars 1.3.0. I do not see why this needs to wait until the release of handlebars ver 2.0.0. It would be great to see a patch applied immediately.
Grunt Options:
options: {
amd: ['handlebars/handlebars.runtime'],
namespace: false
}
Output:
define(['handlebars/handlebars.runtime'], function(Handlebars) {
return Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
return "<h1>Hello World</h1>";
})
});
The problem with the output is that the handlebars AMD implementations expose an object:
Object {default: HandlebarsEnvironment}
I believe it could be immediately fixed with the following commit (minus the package.json update):
@jaridmargolin you can use the approach given by @ixtli in handlebars.js/796 See my comment.
IMHO it is simple as you only need to give require.js a handlebars
object that export the Handlebars.default
.
I can also create a PR with my change that you referenced.
@stephanebachelier I am currently using the approach outlined in 796. However, it would be preferred to not need an additional shim file...
Ok so sorry for taking so long for this, but I'd like to explain how I work around this issue. It's a hack to be sure but I'm 99% sure it's safe and works on everything IE7+. First off I should say that I precompile my templates using the "simple" mode offered by the current version of handlebars (-s option). Doing so turns <div>This is a {{test}}</div>
into
{"compiler":[5,">= 2.0.0"],"main":function(depth0,helpers,partials,data) {
var helper, functionType="function", escapeExpression=this.escapeExpression;
return "<div>This is a "
+ escapeExpression(((helper = helpers.test || (depth0 && depth0.test)),(typeof helper === functionType ? helper.call(depth0, {"name":"test","hash":{},"data":data}) : helper)))
+ "</div>\n";
},"useData":true}
I get a string representing this object via AJAX, so to execute it I including the AMD build as outlined in the thread @stephanebachelier mentioned:
var Handlebars = require('handlebars/handlebars.runtime')['default'];
Then I execute the raw string by doing the following:
function executeScript(raw)
{
// The following is equivalent to
// var script = $('<script>', {'type': 'text/javascript'})[0];
var script = document.createElement('script');
script.type = 'text/javascript';
try {
// Fails on IE7
script.appendChild(document.createTextNode(raw));
} catch (e) {
// IE is stupid
script.text = raw;
}
// This is basically how jQuery implements $.noConflict();
var old = window['NZomIzI2O'];
// If you'd like you can trap errors with try{}catch(){}; here.
_head.insertBefore('window["NZomIzI2O"]=' + script, _head.firstChild);
_head.removeChild(script);
// Save our output to return it
var output = window['NZomIzI2O'];
// Don't destroy global namespace
window['NZomIzI2O'] = old;
return output;
}
So whenever I want to turn a precompiled template in string form into a template I do this:
var template = Handlebars.template(executeScript(rawTemplate));
I believe this approach keeps the application from mutating the global namespace in any reasonable way, and while I do realize that it assumes the presence of a window
object (clearly problematic for certain runtimes) this is my use case :) I also realize this is a hack, but I need to load arbitrary sets of templates in an environment without access to async loading features of requirejs and I'd rather not put eval()
in my code. Also it needs to get done now. I look forward to unhacking, to a degree when grunt-contrib-handlebars gets update so I'm happy letting this serve as documentation of a legitimate use-case.
I have a project set up using bower handlebars shim library, which contains the runtime (compiler free) library and the library using amd. I' using contrib-requirejs to compile my setup. { amd: true, wrapped: false } https://github.com/wycats/handlebars.js/issues/547#issuecomment-29741820 The error in with .merge method no error in that comment is still happening. This repo: https://github.com/components/handlebars.js is using the latest version of handlebars.
Shouldn't this library using the AMD config compile templates to be preferably used by handlebars.runtime.amd? when I hardcode ['runtime.amd'] in the compiled template the library returns all handlebars methods inside a 'default' object therefore the methods aren't found in Handlebars properly.
Not sure if I should add more handlebars compiler variables to make this happen. If this is the case there should be a sample in the readme.