0
votes

Hi I want to render same template with different data inside a meteor template using Meteor.render. My problem is whenever parent template re-renders it destroys template rendered using Meteor.render. I'm new to meteor and not sure is this the right way to do this thing. Please help. I'm sharing my test code:

test.html

<head>
  <title>test</title>
</head>

<body>
  {{> test}}
</body>

<template name="test">
  <div style="margin: 10px;">
    <input type="button" id="render" value="Render">
    <input type="button" id="resize" value="Resize">
    <div id="placement" style="padding: 10px; background-color: #eee; width: {{width}}px; height: {{height}}px"></div>
  </div>
</template>

<template name="temp">
    <h1>{{name}}</h1>
</template>

test.js

if(Meteor.isClient){
  Template.test.helpers({
    height: function() {
      return Session.get("size");
    },
    width: function() {
      return Session.get("size");
    }
  });

  Template.test.created = function() {
    Session.set("size", 200);
    Session.set("name", "Dal Chand");
  }

  Template.test.events({
    'click #render': function(event, template) {
      var frag = Meteor.render(function(){
        return Template.temp({name: Session.get("name")});
      });
      var el = document.getElementById('placement');
      if(el) el.appendChild(frag);
    },
    'click #resize': function(event, template) {
      var size = Session.get("size");
      Session.set("size", (size + 100) % 500 + 300);
    } 
  });
}

So the problem here is when I click on Resize button it removes temp template from the DOM

1

1 Answers

1
votes

It depends what you're looking to achieve, but you can make much better use of reactivity in the templates here, rather than using JS to insert new DOM elements, which will generally just get in the way of what Meteor is doing (as you have found).

Try:

...
<template name="test">
  <div style="margin: 10px;">
    <input type="button" id="render" value="Render">
    <input type="button" id="resize" value="Resize">
    <div id="placement" style="padding: 10px; background-color: #eee; width: {{width}}px; height: {{height}}px">
        {{#if renderTemp}}{{> temp}}{{/if}}
    </div>
  </div>
</template>
...

and

if(Meteor.isClient){

Session.set('renderTemp', false);

  Template.test.helpers({
    height: function() {
      return Session.get("size");
    },
    width: function() {
      return Session.get("size");
    }
  });

  Template.test.helpers({
    renderTemp: function() {
      return Session.get('renderTemp');
    }
  })

  Template.test.created = function() {
    Session.set("size", 200);
    Session.set("name", "Dal Chand");
  }

  Template.temp.helpers({
    name: function() {
      return Session.get("name");
    }
  })

  Template.test.events({
    'click #render': function(event, template) {
      Session.set('renderTemp', true);
    },
    'click #resize': function(event, template) {
      var size = Session.get("size");
      Session.set("size", (size + 100) % 500 + 300);
    } 
  });
}

There are also ways you can achieve reactivity without having to declare Session variables, which can often be neater - see here. If the behaviour on clicking "Render" needs to be more complex or there are circumstances under which you'd want to hide the temp Template again, just put the logic in the relevant event handlers.

UPDATE: As a final point, it's not clear why you're using Template.test.created. Session variables are available anywhere (on the client), so you're probably best setting these up somewhere at the top of the file rather than waiting for a template to be created, in case you try to reference name in some other piece of code and it hasn't yet been set the first time that piece of code runs (because templates are still being rendered). Just a thought.