mustache / mustache.github.com

The {{official}} website
http://mustache.github.io/
Other
2.32k stars 293 forks source link

Context name from list #136

Closed leonardopsantos closed 11 months ago

leonardopsantos commented 3 years ago

I'm trying to render a list of values. In my real problem, each list item has a name property, and also another list, in which the items also have a 'name' property. I'm trying to avoid renaming the nested list items in my context.

I've done some testing and I figure out that this works perfectly:

        template = '''
{{#my_list}}
My list name is: {{my_list.name}}
{{/my_list}}
'''
        context = {'my_list' : {'name': 'This is my first item'}}

        renderer = pystache.Renderer(missing_tags='strict')
        s = renderer.render(template, context)
        print(s)

The output is what you expect:

My list name is: This is my first item

However, if my_list is actually a list (like it is in my actual problem), this breaks:

        context = {'my_list' : [
                {'name': 'This is my first item'},
                {'name': 'This is my second item'}
            ]}

I've tried with Pystache and Chevron, and they don't work, I get:

My list name is: 
My list name is:

My question is: should it work according to the specs?

Thanks a lot!

jobol commented 3 years ago

Have you tried to put {{name}} instead of {{my_list.name}} ? If no then try.

leonardopsantos commented 3 years ago

Have you tried to put {{name}} instead of {{my_list.name}} ? If no then try.

Thanks for your reply, but if you look at my problem description, it won't work:

In my real problem, each list item has a name property, and also another list, in which the items also have a name property.

This means that when the nested list gets rendered, {{name}} will be the data form the nested list, I'm trying to disambiguate between the two name fields.

My end goal with this is to try to solve this problem:

template = '''
{{#my_list}}
{{#sublist}}
{{name}} from {{name}}
{{/sublist}}
{{/my_list}}
'''

context = {'my_list' : [
        {'name': 'list first item',
         'sublist' : [
             {'name': 'sublist first item'},
             {'name': 'sublist second item'}
          ]},
        {'name': 'list second item',
         'sublist' : [
             {'name': 'sublist first item'},
             {'name': 'sublist second item'}
          ]}
    ]}

And I want this rendered:

sublist first item from list first item
sublist second item from list first item
sublist first item from list second item
sublist second item from list second item

But I get this rendered:

sublist first item from sublist first item
sublist second item from sublist second item
list second item from list second item
list second item from list second item

I thought that having a template with named elements would solve my problem:

template = '''
{{#my_list}}
{{#sublist}}
{{sublist.name}} from {{my_list.name}}
{{/sublist}}
{{/my_list}}
'''
jobol commented 3 years ago

Are you forced to use the same key 'name'?

leonardopsantos commented 3 years ago

I'm trying to avoid renaming the nested list items in my context.

Yes, I'd like to keep using the same name.

jobol commented 3 years ago

In your example, there is a blind array index in my_list[].name and sublist[].name

That is obvious but implicit. At the end if it works, it should remain implicit i guess

leonardopsantos commented 3 years ago

In your example, there is a blind array index in my_list[].name and sublist[].name

That is obvious but implicit. At the end if it works, it should remain implicit i guess

I'm not sure what you mean by 'At the end if it works'. It doesn't work.

Is this something that should be supported by the specs? I'm not asking this to be supported, I'm just asking if this example should work according to the specs (and thus it's an implementation problem with Pystache and Chevron), or if this example is not supported by Mustache at all.

Thanks!

leonardopsantos commented 3 years ago

My current 'solution' is to name every single list element:

template = '''
{{#my_list}}
{{#my_list_item.sublist}}
{{name}} from {{my_list_item.name}}
{{/my_list_item.sublist}}
{{/my_list}}
'''

context = {'my_list' : [
        { 'my_list_item' : 
            {'name': 'list first item',
             'sublist' : [
                 {'name': 'sublist first item'},
                 {'name': 'sublist second item'}
                 ]
            }
        },
        { 'my_list_item' : 
            {'name': 'list second item',
             'sublist' : [
                 {'name': 'sublist first item'},
                 {'name': 'sublist second item'}
              ]
            }
        }
    ]}

name is taken from sublist and of course my_list_item.name is taken from my_list_item.

phspies commented 2 years ago

I'm having the same issue with nested arrays. This fiddle shows how the nested loops cannot cross access each other's objects: http://jsfiddle.net/L0zak1x8/7/

Not sure if this is expected.

var context = {
  "families" : [
        {
          "surname": "Jones",
          "members": [
            {"given": "Jim"},
            {"given": "John"},
            {"given": "Jill"}
          ]
        },
        {
          "surname": "Smith",
          "members": [
            {"given": "Steve"},
            {"given": "Sally"}
          ]
        }
      ]
};
  <ul>
    {{#families}}
    <li>{{surname}}
      <ul>
        {{#members}}
        <li>name: {{given}} surname: {{../surname}}</li>
        {{/members}}
      </ul>
    </li>
    {{/families}}
  </ul>
jgonggrijp commented 11 months ago

This is an unsolved problem in the Mustache language. Some implementations offer solutions, but there is no standard solution yet.

You can find previous discussion about this issue via https://github.com/mustache/spec/discussions/154.

Closing this, as this repository is only about the Mustache website, not about the template language.