twitter / hogan.js

A compiler for the Mustache templating language
http://twitter.github.io/hogan.js
Apache License 2.0
5.14k stars 431 forks source link

Can't get lambdas to work #199

Closed prashaantt closed 10 years ago

prashaantt commented 10 years ago

I recently commented on #75 but realised it was closed while this one deserves a current issue of its own.

I just tested with the last v1 release (1.0.5) that I'm able to define a function like

var foo = function () {
  return function(text, render) {
    return bar(render(text));
  }
}

which I can then use with a template like {{#foo}}{{baz}}{{/foo}}. This works delightfully and solves all my templating problems.

I'm unable to get this behaviour working v2 onwards: I see the ugly Uncaught ReferenceError: render is not defined for the exact same code. Did something break along the way for it to be thus or am I missing something?

Maksims commented 10 years ago

Looks like calling "render" is not required anymore, so just do:

var foo = function () {
    return function(text) {
        return text + '<b>whatever and {{test}}</b>';
    }
}

Even if they are template tags it will just work.

Check solution bellow to replicate exact behaviour of previous functionality.

prashaantt commented 10 years ago

That's not the same thing. render(text) gives you the rendered value of the template, while text gives you just the template itself. So you can't manipulate the data for text before you render it.

Hogan devs, @sayrer / @fat / others, I'd like to draw your attention to this issue, can you please help? I'm stuck with using 1.x until I'm able to get this working.

Maksims commented 10 years ago

You can compile and render template yourself, like so:

var foo = function () {
    return function(tpl) {
        return bar(Hogan.compile(tpl).render(this));
    }
}

Where "this" will point to object of data with current templating scope, which you can access the way you want.

prashaantt commented 10 years ago

Actually, you're right. I just saw the test and they're doing it the same way. But this isn't documented anywhere and it kind of breaks the Mustache standard. It would be great if the devs could explain the rationale behind this change.

Maksims commented 10 years ago

Some off topic, but new way is better as it exposes template to you, and you can actually cache templates by key (might be hash) of template, so that Hogan is not responsible for doing such specific thing. Sometimes there is no rendering required as well.

sayrer commented 10 years ago

The spec says the argument to a section lambda is to be the unprocessed template text. This change was intentional. I know it changed from 1.x. It's one of the reasons we had to bump the version, as it was incompatible.

MeTaNoV commented 9 years ago

This differs then from the Mustache definition that could be find there: http://mustache.github.io/mustache.5.html where you get both the text as template and the render function ready to be used. This was practical because you are force to reintroduce now a dependency on Hogan where your implementation needs the rendering...

Jerska commented 9 years ago

:+1: On @MeTaNoV comment.

http://twitter.github.io/hogan.js/ clearly states that everything should be handled the same way than in the mustache spec, and this clearly isn't the case.

Here is somewhat of a fix :

  var renderer = function (self) {
    return function (text) {
      return Hogan.compile(text).render(self);
    };
  };
  var createLambda = function (lambda) {
    return function () {
      return function (text) {
        return lambda.call(this, text, renderer(this));
      };
    };
  };

And then I create my lambdas like this :

createLambda(function(text, render) {
    return bar(render(text));
});
MichielDeMey commented 9 years ago

Thanks guys, I had the same issue. I guess I expected Hogan to work as described in the Mustache(5) syntax, with an injected render function.