Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{{if conditionalProperty1 || conditionalProperty2}} fails #70

Closed
mattfysh opened this issue Feb 10, 2011 · 6 comments
Closed

{{if conditionalProperty1 || conditionalProperty2}} fails #70

mattfysh opened this issue Feb 10, 2011 · 6 comments

Comments

@mattfysh
Copy link

Given the following template data:

[{
    conditional1: true
}, {
    conditional2: true
}, {
    conditional1: true,
    conditional2: true
}, {

}];

These two both work

{{if conditional1}}

{{if conditional2}}

However, this silently fails and nothing is rendered

{{if conditional1 || conditional2}}

I've only been able to get this to work so far through the use of $data

A conditional value {{if $data.conditional1 || $data.conditional2}} does {{else}} doesn't {{/if}} exist
@BorisMoore
Copy link
Owner

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
}]

@mattfysh
Copy link
Author

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:

  1. The following works

    {{if $data.conditional1 || $data.conditional2}}
    
  2. 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 :)

@BorisMoore
Copy link
Owner

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...

@mattfysh
Copy link
Author

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 ) {} } )

@BorisMoore
Copy link
Owner

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...

@mattfysh
Copy link
Author

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!

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants