Closed mattfysh closed 13 years ago
That is because you are passing a javascript expression containing variables which may be undefined. The template engine can check if you pass a single variable that is undefined: if conditional1, but cannot help the javascript engine to figure what to do with an expression that contains undefined variables within it: if conditional1 || conditional2.
So the solution is either:
{{if conditional1}}
{Success
{{else conditional2}}
Success
{{/if}}
or use this for you data:
[{
conditional1: true,
conditional2: false
}, {
conditional1: false,
conditional2: true
}, {
conditional1: true,
conditional2: true
}, {
conditional1: false,
conditional2: false
}]
It seems rather counter-intuitive to repeat the same 'Success' content twice, especially with extensive markup. There are two reasons why this should work as expected:
The following works
{{if $data.conditional1 || $data.conditional2}}
It is a valid JavaScript expression, and the API doc doesn't mention any restrictions for
{{if expression}}
I've forked the project, so I'll take a look this weekend. Besides this small issue, the entire project is nothing short of amazing. I can't even begin to imagine how many hours I've saved using it :)
Sure, you would use {{if $data.conditional1 || $data.conditional2}}
to avoid repeated content. Just showed you the other form to show how the templates engine can be smart about top-level undefined, but cannot prevent the javascript engine from throwing if you have expressions containing undefined variables. The javascript engine will consider that
if (foo.undefinedField)
is equivalent to if (false)
. But if ( undefinedVariable )
will fail to execute - and will throw:
a={x:1}
if (a.x) {"yes"} else { "no" }
"yes"
if (a.foo) {"yes"} else { "no" }
"no"
if (foo) {"yes"} else { "no" }
'foo' is undefined
So if ( foo ) is a valid expression but will still throw...
The only alternative is for the tmpl implementation to wrap things in try catch blocks. We'll be looking at this kind of possibility for better error handling in a future (Beta2) release...
Right, that makes much more sense. I get where you're coming from now, but shouldn't all variables in a template be resolved against the current data object? That is,
{{if conditional1 || conditional2}}
Should automatically be interpreted as
{{if $data.conditional1 || $data.conditional2}}
I guess the cleanest way to implement this would be
{{if $item.hasConditional()}}
Initiating the template like so
.tmpl( data, {hasConditional: function(return this.data.conditional1 || this.data.conditional2 ) {} } )
You can provide the hasConditional function on $item, as you suggest, yes, or you can include $data.conditional in your template, or you can ensure conditional1 and conditional2 are defined (true or false) on your data...
But the template engine can't tell the JavaScript interpreter to interpret {{if conditional1 || conditional2}}
as {{if $data.conditional1 || $data.conditional2}}
. And we don't want to be in the game of parsing JavaScript expressions, and figuring out where the variables are, and appending "$data."
to them. Once you provide an expression, it will run as is...
True, the parsing of expressions to search for identifiers should be kept well out of scope. I'll use the $item extension instead, much more readable :) Thanks Boris!
Given the following template data:
These two both work
However, this silently fails and nothing is rendered
I've only been able to get this to work so far through the use of $data