valotas / mustache4dart

mustache implementation for Dart
Other
87 stars 15 forks source link

lambdas and nested templates #39

Closed sethladd closed 9 years ago

sethladd commented 9 years ago

Hi,

How do we handle this case?

Consider:

var map = {
  'people': [
    'bob': {
      'firstName': 'Robert'
    }
  ]
};
{{#map.people}}
  {{#lambda}}{{firstName}}{{/lambda}}
{{/map.people}}

Notice that firstName is scoped to an implicit person.

If you remove the lambda, firstName is included in the output.

If you include the lambda, firstName is NOT included in the output. I believe this is because lambdas are required to do the mustache processing, and thus need to set the state correctly.

var context = {
  'map': map,
  'lambda': lambda
};

String lambda(String input) {
  return doAwesomeStuff(render(input, context)); // here's the issue. the context is scoped. how do I know the scope?
}

Proposed solution:

If mustache4dart could pass in the current context object into the lambda as the second argument, then all would be good:

String lambda(String input, currentContextPossiblyNested) {
  return doAwesomeStuff(render(input, currentContextPossiblyNested)); 
}

Would something like that work?

sethladd commented 9 years ago

Hm, looking at the spec, a second parameter is passed:

{
  "name": "Willy",
  "wrapped": function() {
    return function(text, render) {
      return "<b>" + render(text) + "</b>"
    }
  }
}

Perhaps in this example, the render function is scoped to the implicit context.

For your implementation, you can pass me a render function or a context. Either way, should work :)

valotas commented 9 years ago

Let me have a look at it tonight and get back to you.

sethladd commented 9 years ago

Thanks for taking a look!

valotas commented 9 years ago

This is against the specs. As discussed in #40 do you have an example where this is a showstopper? You provide the lambda, so you should know it's context.

I think that we could support it with an optional parameter, but I'll need some time to fix that which means not before the weekend :)

sethladd commented 9 years ago

The tests don't cover my situation. See code in description... using lambdas inside of a loop, which requires the lambda to understand the current context (and not the global context). Note how {{firstName}} , which is inside of the lambda, is relative to the current value of the loop. My lambda function requires the current context to be passed in, because otherwise I don't know which index of the loop we're in.

This is not an academic example problem, this is extracted from a real-life usage of mustache in our new dartdoc tool. So yes, it's a show stopper.

I'd be fine with mustache4dart checking the lambda function for one or two parameters. As long as it's possible to pass in a second parameter that is the current context.

valotas commented 9 years ago

OK, I'll try to provide a solution there with an optional parameter.