ractivejs/ractive

Why doesn't {{#with}} set context when it's nested?

ceremcem opened this issue · 3 comments

Description:

I remember (but I'm unsure) that we could use {{#with foo}} to set the context to foo. It still works the same way, but not with nested structures. Why is that?

Versions affected:

1.4

Platforms affected:

Browser

Reproduction:

Ractive({
  el: 'body',
  append: true,
  data: {
    foo: {
    }
  },
  template: `
    <!-- context becomes foo -->
    {{#with foo as f}}
      <input value="{{f.hello}}" />
      {{#with f.bar as b}}
      	<input value="{{b.yay}}" />
      {{/with}}
    {{/with}}
  `,
  onrender: function(){
    console.log(JSON.stringify(this.get()))
  }
})

This code prints the expected output: {"foo":{"bar":{"yay":""},"hello":""}}

However, this simplified version produces an undesired result:

Ractive({
  el: 'body',
  append: true,
  data: {
    foo: {
    }
  },
  template: `
    <!-- context becomes foo -->
    {{#with foo}}
      <input value="{{hello}}" />
      {{#with bar}}
      	<input value="{{yay}}" />
      {{/with}}
    {{/with}}
  `,
  onrender: function(){
    console.log(JSON.stringify(this.get()))
  }
})```

Outputs: `{"foo":{"hello":""}}`

Is this behavior expected?

This is correct according to the tests, even though I agree that it doesn't look right and I've fought with it before. The problem is overloading and historical implementation detail in that originally with was just a plain mustache that's an internal if-with under the covers. To avoid the issue, foo.bar has to be in place in order to render the {{#with bar}} section, which will cause the yay twoway binding to update the model with the empty string.

Do you think this desired behavior may be a feature request?

I've definitely got it on my list for Ractive 2.0.