Function returned by helper is run instead of being attributed

I found a quite weird behavior when calling a template and wanted to know more about it.

const func1 = () => { console.log('func1 called') };

const func2 = () => { console.log('func2 called') };

Template.parentTemplate.helpers({
  getFunc: (arg) => arg ? func2 : func1,
});
{{> test
  attribute1=getFunc
  attribute2=(getFunc true)
}}

Now comes the weird part. What happens now is that the attribute1 from the test template will receive the func1 function, which I expected. However, where I used attribute2=(getFunc true) will actually run the getFunc helper with true as parameter (everything fine until here), then run the function returned by the helper and, finally, the returned value from this second function will be attributed to attribute2. So there will be a 'func2 called' in the console and the attribute2 will get undefined as its value.

This happens in another case as well.

const func3 = () => { console.log('func3 called') };

Template.parentTemplate.helpers({
  obj: () => { func: func3 },
});
{{#with obj}}
  {{> test
    attribute=func
  }}
{{/with}}

In this case the same that happened to attribute2 happens again. Instead of the value in func (a function) being attributed to attribute, it’s run (therefore we see 'func3 called' in the console), and then its returned value is attributed to attribute (in this case, undefined) .

So what I said makes sense? If so is the implication that I can actually run any function in a Blaze template, and not just helpers? Or I just did something wrong? For some reason it looks like an unexpected behavior, but maybe it’s just me.

Also, is there a way for me to call a helper with parameters that returns a function and then attribute this function, and not run it?

Yeah, this seems to be an expected behavior from Blaze, it will automatically run the functions passed to the template (Weird behaviour when passing functions from helpers · Issue #47 · meteor/blaze · GitHub).

One way to pass functions as parameters to another templates is to pass it inside an object, for example:

Template.test1.helpers({
  paramsForOtherTemplate() {
    return {
      functionTest() {
        console.log("Hello from console!");
      },
    };
  },
});

Template.test2.events({
  "click #button1"(event, instance) {
    const { functionTest } = instance.data;
    if (functionTest) functionTest();
  },
});

And then on your HTML:

<template name="test2">
  <button id="button1">Button 1</button>
</template>

<template name="test1">
  {{>test2 paramsForOtherTemplate }}
</template>
2 Likes

Thanks for the information!:slight_smile:

There’s just one point I’m still confused. Why is it that when we pass a helper with no arguments that returns a function then this function is not run? For example, the attribute1=getFunc I used in the code in my original post above.