I have the following template:
<template name="modalTest">
{{session "modalTestNumber"}} <button id="modalTestIncrement">Increment</button>
</template>
That session
helper simply is a go-between with the Session
object. I have that modalTestNumber
initialized to 0
.
I want this template to be rendered, with all of it's reactivity, into a bootbox modal dialog. I have the following event handler declared for this template:
Template.modalTest.events({
'click #modalTestIncrement': function(e, t) {
console.log('click');
Session.set('modalTestNumber', Session.get('modalTestNumber') + 1);
}
});
Here are all of the things I have tried, and what they result in:
bootbox.dialog({
message: Template.modalTest()
});
This renders the template, which appears more or less like 0 Increment (in a button)
. However, when I change the Session
variable from the console, it doesn't change, and the event handler isn't called when I click the button (the console.log
doesn't even happen).
message: Meteor.render(Template.modalTest())
message: Meteor.render(function() { return Template.modalTest(); })
These both do exactly the same thing as the Template
call by itself.
message: new Handlebars.SafeString(Template.modalTest())
This just renders the modal body as empty. The modal still pops up though.
message: Meteor.render(new Handlebars.SafeString(Template.modalTest()))
Exactly the same as the Template
and pure Meteor.render
calls; the template is there, but it has no reactivity or event response.
Is it maybe that I'm using this less packaging of bootstrap rather than a standard package?
How can I get this to render in appropriately reactive Meteor style?
Hacking into Bootbox?
I just tried hacked into the bootbox.js
file itself to see if I could take over. I changed things so that at the bootbox.dialog({})
layer I would simply pass the name of the Template I wanted rendered:
// in bootbox.js::exports.dialog
console.log(options.message); // I'm passing the template name now, so this yields 'modalTest'
body.find(".bootbox-body").html(Meteor.render(Template[options.message]));
body.find(".bootbox-body").html(Meteor.render(function() { return Template[options.message](); }));
These two different versions (don't worry they're two different attempts, not at the same time) these both render the template non-reactively, just like they did before.
Will hacking into bootbox make any difference?
Thanks in advance!
This works for Meteor 1.1.0.2
Assuming we have a template called changePassword that has two fields named oldPassword and newPassword, here's some code to pop up a dialog box using the template and then get the results.
In order to render Meteor templates programmatically while retaining their reactivity you'll want to use
Meteor.render()
. They address this issue in their docs under templates.So for your handlers, etc. to work you'd use:
This was a major gotcha for me too!
I see that you were really close with the
Meteor.render()
's. Let me know if it still doesn't work.I am giving an answer working with the current 0.9.3.1 version of Meteor. If you want to render a template and keep reactivity, you have to :
So this very short function is the answer to do that :
In your case, you would do :
Using the latest version of Meteor, here is a simple way to render a doc into a bootbox
If you want the dialog to be reactive use
Answer for Meteor 1.0+:
Use Blaze.render or Blaze.renderWithData to render the template into the bootbox dialog after the bootbox dialog has been created.
This assumes you have a template defined:
Template.myDialog
is created for every template you're using.$("#dialogNode")[0]
selects the DOM node you setup inAlternatively you can leave
message
blank and use$(".bootbox-body")
to select the parent node.As you can imagine, this also allows you to change the
message
section of a bootbox dialog dynamically.