Batman.js is a CoffeeScript front-end MVC framework. One of its core features is accessors, which can be used like properties or methods of a
Batman.Object. They can even take arguments!
Batman.Object has properties defined with
@accessor in the class definition. Examples of
@accessor as accessible properties and computed properties are bountiful. However, I recently learned that accessors can also be made to take arguments, too!
(You can see this example live on at http://jsbin.com/dalodifo/3/edit .)
Definining Accessors with Arguments
To make an accessor that takes arguments, use
Batman.TerminalAccessible. Let’s say I have a
MathObject which stores a
value and allows you to perform calculations on it:
class MathObject extends Batman.Object @accessor 'value' @accessor 'times', -> new Batman.TerminalAccessible (multiplier) => @get('value') * multiplier
times accessor takes an argument (
multiplier) and returns the multiplied value. I pass the argument with
get, like this:
fiveObject = new MathObject(value: 5) fiveObject.get('time').get(10) # => 50 fiveObject.get('time').get(3) # => 15
Under the hood,
fiveObject.get('time') returns a
Batman.TerminalAccessible. This object provides source tracking for the function that it calls.
Objects as Arguments
You can also have
Batman.Objects as arguments. For example, if we wanted to multiply two
class MathObject extends Batman.Object @accessor 'value' @accessor 'timesMathObject', -> new Batman.TerminalAccessible (mathObj) => @get('times').get(mathObj.get('value'))
Now, the other
mathObj will be included in the source tracking. If
mathObj.value changes, the value will be recalculated. This is essential for values computed from two
What’s the point?
This allows observable “method calls”. It’s wrapped in batman.js source tracking, so whenever the object or the arguments change, the value will be recalculated.
For example, I use it for checking whether a room is at maximum occupancy for certain events:
location.get('isFullFor').get(earlyEvent) # => false location.get('isFullFor').get(lateEvent) # => true
When people attend the event (or the location max occupancy is changed), these values are automatically recalculated!
This is the same approach used in batman.js internals for accessing SetIndexes (source).
Accessor Arguments in View Bindings
To pass arguments to accessors in view bindings, you can use the
withArguments filters. Let’s say I want to put this operation in a view binding:
[...] is shorthand for calling
get with the given argument. I can use it like this:
earlyEvent will be looked up in context and the value will be passed to
get, as in the CoffeeScript above.
You can also use the
withArguments filter (as of 0.16, PR) like this:
<span data-bind='location.isFullFor | withArguments earlyEvent'></span>
withArguments recognizes that it should use
get in this case.