leonidas / transparency

Transparency is a semantic template engine for the browser. It maps JSON objects to DOM elements by id, class and data-bind attributes.
http://leonidas.github.com/transparency/
MIT License
969 stars 112 forks source link

Handling directive nesting levels with list #54

Closed miohtama closed 12 years ago

miohtama commented 12 years ago

Here is a complex, yet a common use case.

I am not sure really sure if this use case

I have created a spec test case how I think Transparency should work, as this comes from natural how you are playing with API. The gap in the thinking is between how to bind products template namelink part to be populated as a directive from an individual list item.

it "should handle directives of several nesting levels with lists", ->
  template = $ """
    <table id="checkout">
      <tbody class="products">
        <tr>
          <td data-bind="id" />
          <td>
            <a data-bind="namelink">
          </td>
          <td>
            <span data-bind="price"> EUR
          </td>
        </tr>
      </tbody>
    </table>
    """

  data = [
    id : 1
    price: 100
    name : "Doggy statue"
    link : "#"
  ,
    id : 2
    price: 200
    name : "Catty statue"
    link : "#"
  ]

  directives =
    products:
      namelink:
        text: -> return @name
        href: -> return @link

  expected = $ """
    <table id="checkout">
      <tbody class="products">
        <tr>
          <td data-bind="id">1</td>
          <td><a href="#">Doggy statue</a></td>
          <td><span data-bind="price">100</span></td>
        </tr>
        <tr>
          <td data-bind="id">2</td>
          <td><a href="#">Catty statue</a></td>
          <td><span data-bind="price">200</span></td>
        </tr>          
      </tbody>
    </table>
    """

  template.render data, directives

  # Render twice to make sure the class names are not duplicated
  template.render data, directives
  expect(template.html()).htmlToBeEqual expected.html()    

And the output (you see that data-bind="namelink" is being ignored for now)

 <tbodyclass="products"><tr><tddata-bind="id">1</td><td><adata-bind="namelink"></a></td><td><spandata-bind="price">100</span></td></tr></tbody><tbodyclass="products"><tr><tddata-bind="id">2</td><td><adata-bind="namelink"></a></td><td><spandata-bind="price">200</span></td></tr></tbody>

<tbodyclass="products"><tr><tddata-bind="id">1</td><td><ahref="#">doggystatue</a></td><td><spandata-bind="price">100</span></td></tr><tr><tddata-bind="id">2</td><td><ahref="#">cattystatue</a></td><td><spandata-bind="price">200</span></td></tr></tbody>
pyykkis commented 12 years ago

Hi, the reason is that data is not nested (top-level anonymous list), but the directives are. The nesting in directives should match the nesting in data as top-level directives are executed for top-level (anonymous) lists and child directives are executed for child lists etc.

Here's the working example

it "should handle directives of several nesting levels with lists", ->
  template = $ """
    <table id="checkout">
      <tbody class="products">
        <tr>
          <td data-bind="id" />
          <td>
            <a data-bind="namelink">
          </td>
          <td>
            <span data-bind="price"> EUR
          </td>
        </tr>
      </tbody>
    </table>
    """

  data = 
    products: [
      id : 1
      price: 100
      name : "Doggy statue"
      link : "#"
    ,
      id : 2
      price: 200
      name : "Catty statue"
      link : "#"
    ]

  directives =
    products:
      namelink:
        text: -> return @name
        href: -> return @link

  expected = $ """
    <table id="checkout">
      <tbody class="products">
        <tr>
          <td data-bind="id">1</td>
          <td><a href="#">Doggy statue</a></td>
          <td><span data-bind="price">100</span></td>
        </tr>
        <tr>
          <td data-bind="id">2</td>
          <td><a href="#">Catty statue</a></td>
          <td><span data-bind="price">200</span></td>
        </tr>          
      </tbody>
    </table>
    """

  template.render data, directives

  # Render twice to make sure the class names are not duplicated
  template.render data, directives
  expect(template.html()).htmlToBeEqual expected.html()
miohtama commented 12 years ago

Thanks for the help. I have the working test code in the branch in the case you want to incorporate this test case for the potential future regression. I can make a pull request.

pyykkis commented 12 years ago

Yes please, I'll take it in!