Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bootboxjs: how to render a Meteor template as dialog body

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!

like image 645
blaineh Avatar asked Dec 26 '22 11:12

blaineh


1 Answers

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 :

  • Render template in a parent node
  • Have the parent already in the DOM

So this very short function is the answer to do that :

    renderTmp = function (template, data) {
        var node = document.createElement("div");
        document.body.appendChild(node);
        UI.renderWithData(template, data, node);
        return node;
    };

In your case, you would do :

    bootbox.dialog({
        message: renderTmp(Template.modalTest)
    });
like image 112
Karl.S Avatar answered Jan 13 '23 11:01

Karl.S