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

Key scopes are mixed when key is not present #98

Closed
lorden opened this issue Jul 11, 2012 · 2 comments
Closed

Key scopes are mixed when key is not present #98

lorden opened this issue Jul 11, 2012 · 2 comments

Comments

@lorden
Copy link

lorden commented Jul 11, 2012

When I'm iterating over an array where the key are duplicated in different places, the rendering changes the scope if the key is not found. Take a look at this example:

<?php
$data = array(
    'set' => array(
        'hidden' => true,
        'fields' => array(
            0 => array(
                'name' => 'email',
                'hidden' => false
                ),
            1 => array(
                'name' => 'password'
                ),
            2 => array(
                'name' => 'session',
                'hidden' => true
                )
        )
    )
);

$template = <<<T
{{#set}}
    {{#hidden}}HIDDEN!<br/>{{/hidden}}
    {{#fields}}
        Name:{{name}} {{#hidden}}is hidden{{/hidden}}<br/>                                                                                                                                                                                                                                  
        <br/>
    {{/fields}}
{{/set}}
T;
$m = new Mustache();
echo $m->render($template,$data);

I want the 'password' element to not be hidden because it doesn't have that property, the engine is reading the variable in 'set'.

@bobthecow
Copy link
Owner

That's how variable resolution is supposed to work. Mustache scope isn't a single scope, so much as a scope stack. So inside your {{#fields}} section, your scope is actually:

<?php

[
    ['name' => 'password'],
    [
        'hidden' => true,
        'fields' => [
            0 => ['name' => 'email', 'hidden' => false],
            1 => ['name' => 'password'],
            2 => ['name' => 'session', 'hidden' => true]
    ],
    [
        'set' => [
            'hidden' => true,
            'fields' => [
                0 => ['name' => 'email', 'hidden' => false],
                1 => ['name' => 'password'],
                2 => ['name' => 'session', 'hidden' => true]
            ]
        ]
    ]
];

It walks up the stack until it finds something with that name. The wiki has more info on this.

The standard answer is to either always have your values set, or to name them differently. That said, you can often use dot notation to force resolution in the scope you want.

In fact, it might not be too much of a stretch to say:

  1. Given that {{ . }} resolves as the current top of the stack;
  2. And when any falsey segment in a dotted name is encountered, the whole name yields '';
  3. A name like {{ .name }} should imply {{ [top level scope].name }};
  4. Thus, it must resolve as truthy only if a member of the current scope matches name.

It might be worth trying to push that into spec v1.2.0.

@bobthecow
Copy link
Owner

Closing this one and opening an issue against the spec — mustache/spec#52

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