I'm trying to write a function that will give me a compiled handlebars template (I have all my templates in separate files) using an ajax call to get the template and compile it for use, but I need to use a promise so I can actually use it.
function getTemplate(name){
$.get('/'+name+'.hbs').success(function(src){
var template = Handlebars.compile(src);
//can't return the template here.
});
}
How do I do this with promises so I can do something like:
$("a").click(function(e){
getTemplate('form').done(function(template){
$("body").append(template({
name: "My Name"
})
);
});
});
Chovy, I see you have accepted an answer but you might be interested to know that getTemplate
can, by chaining .then()
rather than .success()
, be written almost as in the question :
function getTemplate(name) {
return $.get('/'+name+'.hbs').then(function(src) {
return Handlebars.compile(src);
});
}
or, adopting charlietfl's idea to pass in data and return a Promise of a fully composed fragment :
function getTemplate(name, data) {
return $.get('/'+name+'.hbs').then(function(src) {
return Handlebars.compile(src)(data);
});
}
The nett effect is identical to charlietfl's version of getTemplate
but .then()
makes it unnecessary to create a Deferred explicitly. The code is thus more compact.
Following adds a data argument to the getTemplate
function as well as template name.
$(function(){
var postData={title: "My New Post", content: "This is my first post!"};
getTemplate('template-1',postData).done(function(data){
$('body').append(data)
})
});
function getTemplate( name,data){
var d=$.Deferred();
$.get(name+'.html',function(response){
var template = Handlebars.compile(response);
d.resolve(template(data))
});
return d.promise();
}
DEMO
I created a library to help with this kind of issue, check at github
You only have to add this to your main app view:
<script type="text/x-handlebars" data-template-name="application">
<!-- Your HTML code -->
<div class="container">
<div class="modal fade" id="editView" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
{{view MainApp.ModalContainerView elementId="modalContainerView"}}
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- modal edit dialog -->
{{view MainApp.AppContainerView elementId="appContainerView"}}
{{outlet}}
</div> <!-- main container -->
</script>
put this into your MainApp
var MainApp = Em.Application.create({
LOG_TRANSITIONS: true,
ready: function () {
/** your code **/
MainApp.AppContainerView = Em.ContainerView.extend({});
MainApp.ModalContainerView = Em.ContainerView.extend({});
/** And other containerView if you need for sections in tabs **/
});
and them, for instance, to open a modal with the template that you want, you only have to:
FactoryController.loadModalTemplate(templateName, callback);
And not forget to add the FactoryController and RepositoryController