Skip to content

Instantly share code, notes, and snippets.

@emdagon
Created May 1, 2015 20:08
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save emdagon/944472f39b58875045b6 to your computer and use it in GitHub Desktop.
Save emdagon/944472f39b58875045b6 to your computer and use it in GitHub Desktop.
Simple Component to include Meteor Templates on React Components
# see https://github.com/reactjs/react-meteor
# and https://github.com/jhartma/meteor-cjsx
@IncludeTemplate = React.createClass
componentDidMount: () ->
componentRoot = React.findDOMNode(@)
parentNode = componentRoot.parentNode
parentNode.removeChild(componentRoot);
Blaze.render @props.template, parentNode
render: (template) ->
<div />
// see https://github.com/reactjs/react-meteor
var IncludeTemplate = React.createClass({
componentDidMount: function() {
var componentRoot = React.findDOMNode(this);
var parentNode = componentRoot.parentNode;
parentNode.removeChild(componentRoot);
return Blaze.render(this.props.template, parentNode);
},
render: function(template) {
return (<div />)
}
});
# see https://github.com/reactjs/react-meteor
# and https://github.com/jhartma/meteor-cjsx
ReactMeteor.createClass
templateName: 'NavbarRight'
getMeteorState: () -> {}
render: () ->
<div id="navbar" className="navbar-collapse collapse">
<ul className="nav navbar-nav navbar-right">
<li><a href="#">Dashboard</a></li>
<IncludeTemplate template={Template._loginButtons} />
</ul>
</div>
@idmontie
Copy link

👍 Works great!

@jdmswong
Copy link

Thank you for this!

I added some garbage collection, so that Blaze will clean up when the component unmounts

IncludeTemplate = React.createClass({
    componentDidMount() {
        var componentRoot = React.findDOMNode(this);
        var parentNode = componentRoot.parentNode;
        parentNode.removeChild(componentRoot);
        // Render the Blaze template on this node
        this.view = Blaze.render(this.props.template, parentNode);
    },
    componentWillUnmount() {
        // Clean up Blaze view
        Blaze.remove(this.view);
    },
    render(template) {
        return (<div />)
    }
});

@brianscroggins24
Copy link

This works great however is this good practice? I'm fairly new to Meteor and have used react a lot before and the general consensus I get is that its bad practice to use blaze templates in react components. However, I want to know what your thoughts are?

@tetratorus
Copy link

parentNode.removeChild(componentRoot);

this line is causing problems with Meteor 1.2

@Batistleman
Copy link

Nice, thanks!

I added template arguments:

    var IncludeTemplate = React.createClass({
        componentDidMount: function() {
            var componentRoot = ReactDOM.findDOMNode(this);
            var parentNode = componentRoot.parentNode;
            parentNode.removeChild(componentRoot);
            return Blaze.render(this.props.template, this.props.data, parentNode);
        },
        render: function(template) {
            return (<div />)
        }
    });

usage:

  <IncludeTemplate template={Template._loginButtons} data={{argument: 'this is an example'}} />

@bikash119
Copy link

@Batistleman : return Blaze.render(this.props.template, this.props.data, parentNode);

Does this statement work because
Blaze.render = function (content, parentElement, nextNode, parentView) , where does it accept data?

@krizka
Copy link

krizka commented Jan 11, 2016

It must be renderWithData I guess. The snippet working for me is:

IncludeBlaze = React.createClass({
    propTypes: {
        template: React.PropTypes.object.isRequired
    },

    componentDidMount() {
        var componentRoot = ReactDOM.findDOMNode(this);
        var parentNode = componentRoot.parentNode;
        // Render the Blaze template on this node
        this.view = Blaze.renderWithData(this.props.template, this.props.data, parentNode, componentRoot);
        parentNode.removeChild(componentRoot);
    },

    componentWillUnmount() {
        // Clean up Blaze view
        Blaze.remove(this.view);
    },

    render() {
        return <div />;
    }
});

The snippet shown in previous comments is not working as expected. The reason is, it tries to render as last child of parent element after all other elements already rendered, not in the place where you leave <IncludeTemplate .../> tag.

@jschlieber
Copy link

Thanks! Works really nice.

For SSR i propose using a string to identify the template, becaues Template is not defined on the server, i.e.

IncludeBlaze = React.createClass({
    propTypes: {
        template: React.PropTypes.string.isRequired
    },

    componentDidMount() {
        var componentRoot = ReactDOM.findDOMNode(this);
        var parentNode = componentRoot.parentNode;
        // Render the Blaze template on this node
        this.view = Blaze.renderWithData(Template[this.props.template], this.props.data, parentNode, componentRoot);
        parentNode.removeChild(componentRoot);
    },

    componentWillUnmount() {
        // Clean up Blaze view
        Blaze.remove(this.view);
    },

    render() {
        return <div />;
    }
});

@Taakn
Copy link

Taakn commented Mar 26, 2016

Thanks works super well. This is the variant I am using with refs:

IncludeBlaze = React.createClass({

    propTypes: {
         template: React.PropTypes.object.isRequired
     },


    componentDidMount() {

        var componentRoot = ReactDOM.findDOMNode(this.container);
        var parentNode = componentRoot.parentNode;
        // Render the Blaze template on this node
        this.view = Blaze.renderWithData(this.props.template, this.props.data, parentNode, componentRoot);
        parentNode.removeChild(componentRoot);

    },

    componentWillUnmount() {
        // Clean up Blaze view
        Blaze.remove(this.view);
    },

    render() {
        return (
          <span
              ref={(c) => this.container = c}
          />
        );
    }
});


module.exports = IncludeBlaze;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment