How to access events and helpers of a child-template in Meteor

时间:2015-10-06 08:27:37

标签: javascript meteor

There is an important edit at the end of this.

My Scenario:

<p>This is the parent template</p>
{{> childComponent }}

The childComponent consists of different UI-Elements allowing the user to generate some input. Think of the childComponent as a number-pad with a return-key <a class="btn" id="submitStuff">Submit</a> and some checkboxes.

The component is going to be used in different places in the app and each of the parent templates (using the component) make a different use of the childComponent's output (the number and the information from the checkboxes). The output is held as an Object in the Session.

What I need to do

When clicking the #submitStuff in the childComponent I want the childComponent's generated Object to be handled by a function in the wrapping parent-template.

What I tried to do (and failed)

Of course I placed all the common behavior of childComponent in it's own template helpers and events. But because each parent template would make another / different use of the child's data (using the number for different purposes and interpreting the checkboxes in different ways), I tried to listen to the submit-button in the childComponent from the parent's context.

Template.parentTemplate.events({
    // trying to listen to the "#submitStuff"-button INSIDE the child-template
    // FAILS --> event is not visible to the outside of the child-component
    'click #submitStuff': function () {
        // get the information from the component
        // nothing happens
    }
});

This would be so easy. Just to place the childComponent anywhere and decide from the parent-context what to do with it's generated value. But it fails.

Does anybody have a suggestion?

I thought about using the Session, but I am no fan of using the global space anytime I use the childComponent.

I thought about defining a function in the parent dealing with the submission and access that function from the childComponent. But I did not get it to work / don't know how to do it.

What do you think?

Thanks in advance!

EDITs

#1

I was hinted to the most straight forward way and simply listen to the event in the parent-template-events. But as I wrote: "I tried to listen to the submit-button in the childComponent from the parent's context." It failed, the event never triggers anything in there (although it should!). When I listen to it from INSIDE the childComponent itself, everything is fine.

This is my setup: http://meteorpad.com/pad/LWNKpfMCatSMhymhN/Copy%20of%20Parent-ChildTemplate

(It works as it should and as it does not in my project).

Does anybody know what could prevent an event from being caught in the parent template?

#2

I just figured out that it has something to do with a plugin that I use: aldeed:template-extension. After commenting out the line Template.parentTemplate.replace('someBaseParent');, it works as expected.

Yet I don't know if I just made a mistake in my way of using the plugin or if there is an issue with it.

1 个答案:

答案 0 :(得分:0)

以下是对默认meteor引导代码的一组最小更改,它们向您展示父模板中的事件(本例中为Template.body)如何侦听子模板中定义的元素上的事件(Template.hello) ,并访问子模板中包含的输入元素的值。

的test.html:

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

<body>
  <h1>Welcome to Meteor!</h1>
  {{> hello}}
</body>

<template name="hello">
  <button>Click Me</button>
  <input type="number" id='num' value="">            // New input element
  <p>You've pressed the button {{counter}} times.</p>
</template>

test.js

if (Meteor.isClient) {
  // counter starts at 0
  Session.setDefault('counter', 0);

  Template.hello.helpers({
    counter: function () {
      return Session.get('counter');
    }
  });

  Template.body.events({                                     // event moved from Template.hello to parent Template.body
    'click button': function () {
      if (Template.instance().find('input').value === '') {  // get value from child template's input element
        // increment the counter when button is clicked                
        Session.set('counter', Session.get('counter') + 1);
      } else {
        Session.set('counter',
           Number(Template.instance().find('input').value)); // get value from child template's input element
        Template.instance().find('input').value = '';        // set value on child template's input element
      }
    },
  });
}

if (Meteor.isServer) {
  Meteor.startup(function () {
    // code to run on server at startup
  });
}

http://meteorpad.com/pad/mNjoRHdRk97cAyx7C/Parent-ChildTemplate