How do you call a Meteor template helper from the console or other JS code?
Asked Answered
R

2

5

I've defined a template helper in Meteor, say

Template.postsList.helpers({
  filteredPosts: function getPosts() {
    return Posts.find(...);
  }
});

How can I debug that template helper from the console, and how can I reuse it from other code in the app?

Rebellious answered 17/8, 2015 at 4:39 Comment(1)
Please take a look at: github.com/anticoders/meteor-helpersExpiatory
R
7
  1. Wanting to call the helper from elsewhere in the app suggests that you should factor it out in a function.

  2. To quickly debug the helper, evaluate this in the client console:

    Template.postsList.__helpers.get('filteredPosts')(...parameters);
    
  3. There is a package that might help with debugging templates and template helpers: prasad19sara:client-debugger.

Rebellious answered 17/8, 2015 at 4:39 Comment(2)
How do I access global helpers?Magnien
@Magnien UI._globalHelpers.yourHelperName(...parameters) to call UI.registerHelper('yourHelperName', function () {})Drin
E
3

It does not formally answer the question but I would like to share a simple technique, which virtually solves most of the problems you described.

Let's say we have a group of helpers, which we want to be able to access from different parts of your application both from templates and directly from our javascript code. To achieve that, I would have a global Helpers object, to which I could attach as many function as I want, e.g.

Helpers.routeIs = function (name) {
  var current = Router.current();
  return current && current.route && current.route.getName() === name;
};

Helpers.year = function () {
  return moment().year();
};

This makes them easily accessible throughout the code and pretty easy to test as well. But I also want to use them in my Spacebars templates, right?

A simple idea is to create a single global helper that would return the Helpers object itself.

Template.registerHelper('$', function () {
  return Helpers;
});

The nice thing about this is that it will enforce me to prefix each reference to my "global helper" with $, i.e. {{$.year}} or {{$.routeIs 'home'}}, which makes the code a lot more readable.

Unfortunately, there's a small problem with that solution. Consider the following example:

Helpers.fullName = function () {
  return this.firstName + ' ' + this.lastName;
};

The problem is that if my helper is about to access the current context through this, it will get the Helpers object itself rather than the data context, so the {{$.fullName}} will never work properly. But of course, there's a workaround for that:

Template.registerHelper('$', function () {
  return new Proxy(this);
});

function Proxy (context) {
  this.context = context;
}

// put this in a place when you're quite sure
// all the helpers are already defined

_.each(Helpers, function (helper, name) {
  Proxy.prototype[name] = function () {
    return helper.apply(this.context, arguments);
  };
});

EDIT

I've added a reference implementation here:

https://github.com/anticoders/meteor-helpers

Expiatory answered 17/8, 2015 at 7:40 Comment(2)
Nice pattern! Would be a nice addition to ostrio:templatehelpers or aldeed:template-extension.Rebellious
Thanks! It's also very useful. I've tested in several projects and it really helps to make things organized.Expiatory

© 2022 - 2024 — McMap. All rights reserved.