Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binding $this to context in function #309

Open
czirkoszoltan opened this issue Jan 27, 2017 · 2 comments
Open

Binding $this to context in function #309

czirkoszoltan opened this issue Jan 27, 2017 · 2 comments

Comments

@czirkoszoltan
Copy link

In mustache.js, when the rendered value is a function, it is called with this bound to the current context, and the return value of the function is htmlescaped as well. So with this template:

<ul>
{{#people}}
    <li> Hello <button onclick="{{onclick}}">{{name}}</button>!
{{/people}}
</ul>

and this data:

  var data = {
      onclick: function () {
          return "alert("+JSON.stringify("ID is " + this.id)+")";
      },
      people: [
        { name: "Alice", id: 1 },
        { name: "Bob", id: 2 },
      ],
  };

the names become clickable, and clicking Alice produces alert "ID is 1", clicking Bob produces alert "ID is 2".
Mustache.php can work with classes (the class Chris example on the intro page), but it cannot work with lambdas like this.
This problem could easily be solved, by changing Template::resolveValue, the line

    ->loadLambda((string) call_user_func($value))

to

    ->loadLambda((string) call_user_func($value->bindTo($context)))

(of course, first checking if the callable is a string)
or maybe by changing the line to

    ->loadLambda((string) call_user_func($value, $context))

to retain compatibility. (Currently callables are expected to have no parameters, so it's no problem in PHP, adding an extra parameter.)
The latter version would allow this:

/* the template is exactly the same */
$template = <<<'EOT'
<ul>
{{#guys}}
    <li> Hello <button onclick="{{onclick}}">{{name}}</button>!
{{/guys}}
</ul>
EOT;

/* the data is the same, the lambda is almost the same as in js, changed this.id to context->find('id') */
$data = [
    'onclick' => function($context) { return $context->find('id'); },
    'guys' => [
        [ 'name'=>"Alice", 'id' => 1 ],
        [ 'name'=>"Bob", 'id' => 2 ],
    ],
];

$m = new Mustache_Engine;
echo $m->render($template, $data);

So lambda function could be used as simply as named classes.

@mAAdhaTTah
Copy link

You would have to drop support for PHP5.3 to do this.

@czirkoszoltan
Copy link
Author

Not for the latter version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants