BorisMoore / jsrender

A lightweight, powerful and highly extensible templating engine. In the browser or on Node.js, with or without jQuery.
http://www.jsviews.com
MIT License
2.67k stars 339 forks source link

for else with empty array #346

Closed sp00n closed 5 years ago

sp00n commented 5 years ago

I'm not sure if this is expected behavior, but the {{else}} condition does not execute when running a {{for someProperty}} loop over an empty array (which naturally doesn't have named properties). With empty objects this works correctly, so at least it seems like an inconsistency to me.

Test case: https://jsfiddle.net/sp00n82/uydr2cp5/

BorisMoore commented 5 years ago

template.render(data.empty_array) returns the empty string, since it iterates for each item in the array, and concatenates. No items means no iteration. Result empty string. It is not rendering your template at all.

If you do template.render(data.empty_array, true) it will render without iteration, and will pass the empty array as context. https://www.jsviews.com/#tmplrender@noiteration

sp00n commented 5 years ago

Still I do wonder why this shouldn't trigger an {{else}} clause. Wasn't that specifically introduced to catch such cases? At least from a user's point of view this seemed like the intended purpose. And since an empty object does trigger the else clause, this also feels a bit inconsistent.

BorisMoore commented 5 years ago

Your code is not actually calling the {{for}} tag at all. You need to understand how iteration works on the render() method. The docs should help (link above).

Your test is not passing an empty object to "for". It is passing an undefined value.

{{for}} does not iterate over properties. Only over array items. To iterate over properties of an object use {{props}}.

To see the symmetry, this would be a better test: See https://jsfiddle.net/43qt6or9/