BorisMoore / jsviews

Interactive data-driven views, MVVM and MVP, built on top of JsRender templates
http://www.jsviews.com/#jsviews
MIT License
855 stars 130 forks source link

for/else does not receive ~var defined in tag "for" #340

Closed Jean-Pierre closed 8 years ago

Jean-Pierre commented 8 years ago

For me it's a bug.

See http://jsfiddle.net/33v3Lah8/1/

{{for testData ~foo=foo }}
    ...
{{else}}
      foo: {{:~foo}}
{{/for}}
albanul commented 8 years ago

@Jean-Pierre You can use foo property from your rm object directly

{{for testData ~foo=foo }} ... {{else}} foo: {{:foo}} {{/for}}

Because testData array is emty there is no need to create new context and you are still in {{for}} tag level of context and that's why there is no ~foo variable.

Jean-Pierre commented 8 years ago

@albanul Thanks, that's right, but this is just a test case.

The else statement contains an included template accepting parameter ~foo without parameter at call time. With your solution you force me to declare ~foo on parent scope if I can't set ~foo in else statement. But it's work.

Paul-Martin commented 8 years ago

Maybe this is what you are trying to do?

{{for testData ~foo=foo }} ... {{else ~foo=foo}} foo: {{:foo}} {{/for}}

.. or ...

{{for testData ~foo=foo }} ... {{else}} {{include tmpl='bar' ~foo=foo /}} {{/for}}

On Jun 24, 2016, at 6:48 AM, Alex Banul notifications@github.com wrote:

@Jean-Pierre You can use foo property from your rm object directly

{{for testData ~foo=foo }} ... {{else}} foo: {{:foo}} {{/for}}

Because testData array is emty there is no need to create new context and you are still in {{for}} tag level of context and that's why there is no ~foo variable.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.

BorisMoore commented 8 years ago

The intended design is that {{else}) tags convert a single block to multiple blocks. They are 'sibling' blocks, and the corresponding views are siblings.

You can actually write:

{{for array1}}
  ... array1 item blocks
{{else array2}}
  ... array2 item blocks (if no array1 items)
{{else}}
  ... no items block (if no array1 or array2 items)
{{/for}}

There you have three sibling blocks, with the following view structure:

Setting a contextual parameter applies to that block, not to sibling blocks, so you can write:

{{for array1 ~prm1=...}}
  ... array1 item blocks - ~prm1 in scope
{{else array2 ~prm2=... }}
  ... array2 item blocks - ~prm2 in scope
{{else ~prm3=...}}
  ... no items block - ~prm3 in scope
{{/for}}

(Similarly you can set properties, such as tmpl=... and the setting will apply just to that block:

{{for array1 tmpl=t1}}
{{else array2 tmpl=t2}}
{{else tmpl=t3}}
{{/for}}

Relevant docs are here:

http://www.jsviews.com/#views http://www.jsviews.com/#elsetag http://www.jsviews.com/#tagsyntax@blocktag (especially section Block tags with {{else}}) http://www.jsviews.com/#contextualparams

I will add to the following content to http://www.jsviews.com/#contextualparams topic to specifically say that you can add contextual parameters to {{else}} blocks: ...


Note: You can also set contextual parameters on {{else}} blocks, such as in the following example which uses the same template for the {{if}} and {{else}} blocks, but assigns different values to the ~teamTitle parameter in each case:

{{if isActive ~teamTitle=activeTitle tmpl="teamTmpl"}}
{{else ~teamTitle=inactiveTitle tmpl="teamTmpl"}}
{{/if}}
Jean-Pierre commented 8 years ago

You cannot say better. Thanks Boris

BorisMoore commented 8 years ago

Documentation updated here: http://www.jsviews.com/#contextualparams. Closing this issue...