Search code examples
meteormeteor-blaze

Meteor, call function in child template from parent template


If I have a parent template Container with a child template Content avec only a button :

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

<body>
    {{> Container}}
</body>

<template name="Container">
    {{# Content callback = callBack }}
        <button>ok</button>
    {{/Content}}
</template>

<template name="Content">
    {{> UI.contentBlock}}
</template>

If can pass a function to the callback. Like that :

Template.Container.helpers( {
    callBack: function () {
        return function () {
            console.log( 'this is my callback' );
        }
    }
} );

So in my content template, I can call a function from my parent template. Like this for instance :

Template.Content.events( {
    'click button': function ( e, tmpl ) {
        tmpl.data.callback();
    }
} );

But sometimes, I need to make it happen the other way. The parent calling a function in his child. What's your way of doing it ?


EDIT :

I saved it in a meteorpad to show it in action and to make it easy to fork : http://meteorpad.com/pad/48NvCFExxW5roB34N/test-pass-callback-to-parent


Solution

  • Here's a pattern you could use. Define a class Child and a template child; the idea is that inside the child template, the data context is a Child instance. For example, I'll create a component which has a number that can be incremented by pressing a button.

    <template name="child">
      <button class="increment">{{number.get}}</button>
    </template>
    
    function Child() {
      this.number = new ReactiveVar(0);
    }
    
    Template.child.events({
      "click .increment": function () {
        this.number.set(this.number.get() + 1);
      }
    });
    

    In the parent's created callback, create a Child instance and store it on the template instance. Then in the parent template, call out to child, passing in the Child as a data context:

    Template.parent.created = function () {
      this.childInstance = new Child();
    }
    
    Template.parent.helpers({
      childInstance: function () {
        return Template.instance().childInstance;
      }
    });
    
    <template name="parent">
      {{> child childInstance}}
    </template>
    

    Now you can define methods on the Child prototype and call them from the parent template, for example:

    Child.prototype.getNumberTimesTwo = function () {
      return this.number.get() * 2;
    }
    
    <template name="parent">
      {{> child childInstance}}
      That number multiplied by two is: {{childInstance.getNumberTimesTwo}}
    </template>