In answer to this tweet:
Within Ractive templates, you can use normal JavaScript expressions (with a handful of exceptions, e.g. no new
operators or assignments, since expressions should be side-effect free). These expressions aren't straightforwardly eval
ed - instead, they're parsed into an abstract syntax tree, at which point we extract the references and turn it back into a string which is later used to generate a function:
Ractive.parse('{{ a+b+1 ? "a" : "b" }}');
// results in
{
t: 2,
x: {
r: ['a', 'b'],
s: '${0}+${1}+1?"a":"b"'
}
}
Those references might mean different things at different times:
<!-- here, `a` might mean `foo.a` or `a` - mutatis mutandis for `b` -->
{{#foo}}
{{ a+b+1 ? "a" : "b" }}
{{/foo}}
<!-- but here, it could mean `bar.a` -->
{{#bar}}
{{ a+b+1 ? "a" : "b" }}
{{/bar}}
In other words, a reference must be resolved to a keypath, taking account of its context. It's those keypaths that are used to set up the reactive data-binding. This can't happen at parse time, because it's dependent on the data the template is rendered with - so it's impossible to evaluate the expression outside the context of a specific point within the template.
Suppose we wanted to use the evaluate an expression anyway, and that we're in a position to say that we don't care about context (i.e. a
and b
are top-level properties), and that we wanted to use the value of that expression in an event handler.
We could do this:
ractive.on( 'foo', function ( event ) {
var a, b, value;
a = this.get( 'a' );
b = this.get( 'b' );
value = a+b+1 ? "a" : "b";
doSomethingWith( value );
});
That's a perfectly valid approach, and one that is easy to understand. But if we wanted or needed to use the expression syntax instead, we could take advantage of the fact that you can pass arguments to event handlers:
<button on-click='foo:{{ a+b+1 ? "a" : "b" }}'>click me!</button>
ractive.on( 'foo', function ( event, value ) {
doSomethingWith( value );
});
This is great advise, and I understand the scope limitation now.
What we are trying to do is to describe entire setup, including events in Json, so functions won't quite work.
There are not that many possible types of actions, - set, fetch data, navigate..
Set is the most important but lot of the times it needs to use a different variable(s) with (get) and do something with it (increment, concat, etc). I guess for all of these assuming top-level scope is fine! So it would work if there would be a way to do something like:
Do you think creating a new instance for this is too wasteful? If there's already a method that's doing it on initial render, maybe it could be exposed to API.
Thanks again