Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 521
fabien Avatar asked Dec 01 '14 13:12

fabien


2 Answers

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>
like image 195
user3374348 Avatar answered Sep 23 '22 02:09

user3374348


Based on my experience with Meteor, it seems like it favors more of an event driven UI design. This means that you would not directly call the parent or child methods directly, but you would fire a custom event or set a Session variable. So you could do something like:

Template.Container.helpers( {
    callBack: function () {
        Session.get('button.lastClickTime');
        console.log( 'this is my callback' );
    }
} );
Template.Content.events( {
    'click button': function ( e, tmpl ) {
        Session.set('buttom.lastClickTime', new Date());
    }
} );

The Session object is reactive so the callback method will be called anytime that 'button.lastClickTime' Session value is set.

Then you could just reverse the set/get calls to notify the child from the parent.

like image 36
desposi1 Avatar answered Sep 26 '22 02:09

desposi1