Closed Rich-Harris closed 11 years ago
I quite like this syntax:
<div class='dialog'>
<p>{{dialogText}}</p>
<a click='closeDialog' class='button'>OK</a>
</div>
It sort of implies that click
is a variable and closeDialog
is the value, which I suppose it is. It gets right to the point and is aesthetically pleasing (to me at least). AFAIK there are no event names that are also valid element attributes, so no collisions. And it is easy to test whether we're dealing with an event directive or an attribute:
if ( node[ 'on' + attrName ] !== undefined ) {
// event directive
} else {
// attribute
}
For the initial implementation I will ignore situations where you need to pass along additional data, or have values that include mustaches. If they turn out to be necessary we can update the implementation.
Hmm. On second thoughts this doesn't work so well. It really needs to be something that can be identified at compile-time, rather than at render time. A good way to do so (and also to disambiguate between these and regular attributes) would be to prefix every attribute. A short but accurately descriptive prefix is proxy
:
<div class='dialog'>
<p>{{dialogText}}</p>
<a proxy-click='closeDialog' class='button'>OK</a>
</div>
I'm going to go with that.
This is a common pattern:
This is fine, as far as it goes, and using jQuery or similar makes it slightly less verbose. But the fact that we're giving an element an ID just so we can easily find it a moment later and bind event handlers to it is a bit... yucky. It goes against the spirit of declarative programming to have to throw in these hooks. Sure, the ID could be more descriptive - 'closeDialog' or something - but that's not really what IDs are for. Our abstractions are leaking.
It would be nicer to be able to do something like this:
That way things are better separated. It also allows us to define multiple behaviours in a nicer way:
Some additional thoughts right off the bat: it would be useful to pass along the event data, and also the element that was the subject of the DOM event (i.e. the event's target or one of its ancestors). Normally with event handlers,
this
is the element, but within aview.on()
handlerthis === view
, and it probably isn't a good idea to change that. A good compromise would be to pass along the element as an argument:So. The real problem to figure out here is what syntax to use in templates to make this happen. It's probably best to use an attribute, as many editors barf if you start throwing illegal characters around inside a document. The colour coding gets messed up. That matters, because the moment that starts happening everything begins to feel like a hack.
For that reason I'm not all that keen on something like Ember's
{{action}}
helper.Angular does it using an
ng-click
attribute (though rather than an event label, you're using pseudo-JavaScript which corresponds to a method on the relevant controller's $scope object). This isn't a bad solution - it means the template doesn't validate as HTML, but who really cares? We could do something similar withrv-click
, or something. I'm not in love with the aesthetics though.One thing we definitely shouldn't do is use an
on-click
attribute or similar, example above notwithstanding. That's too similar toonclick
where the value is eval'ed as JavaScript in the global context. Ugly, ugly, ugly stuff.Two final considerations: