Batman.js is no longer in production at Shopify and is not actively maintained.

This website is left for reference (and for old times' sake).


Batman.SetIndex is a grouped collection of items derived from a Batman.Set filled with Batman.Objects. It extends Batman.Object and Batman.Enumerable, so it inherits methods from them, too. In short, a SetIndex tracks its base Set and contains "buckets" of items from that Set, grouped by the provided key.

test 'SetIndex groups items by values', ->
  batarang = new Batman.Object(name: "Batarang", type: "ranged")
  fists = new Batman.Object(name: "Fists", type: "melee")

  weapons = new Batman.Set(batarang, fists)
  # Three ways to create a SetIndex:
  weaponsByType1 = weapons.indexedBy('type')
  weaponsByType2 = weapons.get('indexedBy.type')
  weaponsByType3 = new Batman.SetIndex(weapons, 'type')

  # additions to the base Set are tracked by the SetIndex
  grappleGun = new Batman.Object(name: "Grapple Gun", type: "ranged")

  for setIndex in [weaponsByType1, weaponsByType2, weaponsByType3]
    equal setIndex.get('ranged').get('length'), 2
    equal setIndex.get('melee').get('length'), 1
    deepEqual setIndex.get('ranged').mapToProperty('name'), ["Batarang", "Grapple Gun"]
    deepEqual setIndex.toArray(), ["ranged", "melee"]

Using a Batman.SetIndex

Batman.SetIndex is batman.js's way of grouping Batman.Sets. A SetIndex is like a hash of Sets. When you get a value from it, the SetIndex returns a Set of matching members.

Since a SetIndex is a proxy of a Set, the easiest way to make one is to use Set::indexedBy:

weaponIndex = weapons.indexedBy('type')

weaponIndex is a SetIndex. To find matches for a type, use get:

meleeWeapons = weaponIndex.get('melee')

meleeWeapons is a Batman.Set containing items where type = "melee".

You can also make SetIndexes in view bindings:

  <li data-foreach-meleeweapon='weapons.indexedBy.type.melee'>
    <!-- will render items where type="melee" -->

SetIndexes are observable proxies of their underlying Sets. So, when the Set is changed (ie, items are added, removed, or modified):

  • The SetIndex is automatically updated by batman.js
  • Any view bindings or accessors depending on the SetIndex are updated
  • constructor(base : Set, key : String ) : SetIndex

    A SetIndex is made with a base and a key. Items in the base set will be grouped according to their value for key. The resulting SetIndex observes its base, so any items added to the base are also added (and indexed) in the SetIndex

  • get(value : String) : Set

    Returns a Batman.Set of items whose indexed key matches value. It returns an empty set if no items match value, but if any matching items are added to the base set, they will also be added to this set.

  • toArray() : Array

    Returns an array with the distinct values of key provided to the constructor.

  • forEach(func)

    Calls func(key, group) for each group in the SetIndex.

Help us improve our documentation!

Contributions to this page are welcome on Github. If you find a problem but you cannot fix it, please open an issue.

Discussion regarding batman.js documentation is also welcome on our mailing list.