Closed dannyc closed 9 years ago
Just use the with
keyword in Javascript. Your feature would be really easy to implement since it's almost the same as the if condition, {{~}}
. I didn't have any time so I didn't try but here's a working solution without hacking doT.js.
Use {{ with ( it ){ }}
, {{ } }}
in place of {{ $ it }}
, {{ $ }}
respectively.
Which gives the following.
var template = "{{with (it){ }}";
template += "<div>I'm {{=name}} and I love..</div>"
template += "<ul>"
template += "{{~interests :value}}"
template += "<li>{{=value}}!</li>"
template += "{{~}}"
template += "</ul>"
template += "<div>Please contact me</div>"
template += "{{ with ( contact ) { }}"
template += "Phone: {{=phone}}<br/>"
template += "Email: {{=email}}"
template += "{{ } }}"
template += "{{ } }}"
Live demo: http://jsfiddle.net/UVFnr/
Personally the auto context in mustache, is the most annoying part about it. I like the option of completely ignoring it, but I also think there are plenty of ways to get it in there without the use of the 'with' keyword. Maybe auto generating closures that accept arguments (varname) that are equivalent to the keys of the context object.
Object it.contact {name: "John", age: 40}
can be converted to (function (name, age) { return // template string }(it.contact.john, it.contact.age))
Probably would be simpler and faster if just prepended the context in the compilation process.
Not sure about the $
character either, but I still like the idea of just concatenating scope automagically to variable names in the compilation.
@LarryBattle 'with' would work though with is better avoided. @drkibitz auto-closures would be better. Concatenating automatically - I don't think this would work as we don't know which variables to concatenate to. One more option is to do something similar to array iterator {{~ it name, age }} where you would have to list properties that you want to use.
@olado I thought concatenation could work something like the following:
{{$ it}}
This is {{foo}} // concatenates to "it.foo"
{{$ bar}}
This is {{foo}} // concatenates to "it.bar.foo"
This is {{it.bar.foo}} // Matched scope variable name, no concatenation
{{$ bar}}
{{$ it}}
This is {{it.baz}} // top level, no concatenation
Basically scope is a stack that always concatenates to the front of variable names.
We know the variable to concatenate from tags that must exist with the variable name.
There are some weird instances here, with the scope matching thing, that might be a bad idea because it.it.it
is not possible with that type of functionality.
Alternatively I do like your Object iteration solution:
{{~ it foo, bar}}
This is {{foo}} // should be value of it.foo
{{~ bar foo}}
This is {{foo}} // should be value of it.bar.foo
This is {{it.bar.foo}} // should also be value of it.bar.foo
{{~ bar}}
{{~ it}}
This is {{it.baz}} // should be value of it.baz
I'm on the fence here. The first is more like other popular template engines that people are use to. Then second is about the same in ease of use, but slightly more characters needed in the template, although very slightly in my comparison.
We don't know which variables to concatenate to because inside of {{ }} can be ANY javascript, not only reference to a variable. This is valid: {{= (function(foo) { return foo; })("hello") }}, same for all other delimiters. Code is allowed in all delimiters, access to global variables is allowed to. Basically all of Javascript is allowed. That's why I don't think automatic would work.
The configurable varname
is one of the absolute best features of doT. Dropping that for the questionable convenience of implicit context reference would be a tragedy (to me).
Another problem with this is that doT syntax allows the expression inside {{= }}
or {{! }}
to be any JavaScript expression. Where would the implicit context go? I suppose that the implicit context thing could apply only to {{= }}
expressions where there's nothing but an identifier, but then that'd mean that for more complicated situations you'd have to remember on your own to add the prefixes.
Hi, It would be nice if there was a context delimeter. Instead of needing to add "it" as a prefix for every data reference.
becomes
Or in a more complex scenario with nesting
Could be used like this:
I roughly tried something along these lines in my fork some time back but never really tested or used it. This give a few big advantages. 1) Easier to read the templates without "it" everywhere. 2) If the data structure ever changes- (i.e. something gets nested inside another object when previously it had not) fixing the template is simply a matter of adding a new context delimiter.
Thoughts? Thanks!