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.Views connect a batman.js application to a user by:

  • rendering HTML templates
  • maintaining view bindings, which bind application objects to the DOM.

Views can be rendered in two ways:

  1. Controller actions render views into yields. Yields are defined in the layout view with data-yield bindings . Content for yields (other than "main") is provided with data-contentfor bindings. This is analagous to the Rails yield pattern.
  2. Views render other views with data-view bindings. Custom views are a great choice for encapsulating UI and display components.

Rendering by Controller Actions

Batman.js handles URLs by dispatching controller actions, which render views. See the "Rendering Views" in the Controller guide for more information about how controller actions render views.

To customize a default view, simply define a class with the expected default name:

Controller Name Action View Name
App.PostsController show App.PostsShowView
App.PostsController new App.PostsNewView
App.PostsController index App.PostsIndexView
App.PostsController edit App.PostsEditView

For example, this view is automatically rendered by the products#index action:

class App.ProductsIndexView extends Batman.View
  # source is "products/index" by default

The Custom Views guide describes all the resources available when defining views.

Rendering with "data-view" Bindings

Views can be inserted into other views by using data-view. This allows you to simplify your HTML and view classes by extracting markup and logic in to reusable custom views.

To use a custom view, pass its name (relative to the app namespace, eg, MyApp) to data-view. For example:

<div data-view='ProductListItemView'>
  <!-- batman.js will instantiate App.ProductListItemView with this node -->

If the custom view has its own HTML, that HTML will replace the contents of the data-view node.

View Lifecycle

As a view is rendered, it fires several lifecycle events. Some events "bubble up" from subviews, so these events may be fired more than once.

One useful event is viewDidAppear, which is called after the view has been added to the DOM. You can initialize your view on viewDidAppear by defining a function with that name:

class MyApp.CustomView extends Batman.View
  viewDidAppear: ->
    if !initialized
      initialized = true

See the Batman.View lifecycle API docs for more information on those events and how to use them.

View Hierarchy

Batman.js stores all active views in a tree, with the layout view as its root. Every view has one superview and any number of subviews. Batman.js manages the view tree internally, so a developer rarely interacts with it directly.

The view tree serves as a rendering context for view bindings, which climb the tree to evaluate keypaths with Batman.View::lookupKeypath.


Batman.js exports the global $context function for debugging views. $context takes a DOM node and returns the batman.js view for that node. For example:

allItems = $('#all_items')[0]
view = $context(allItems)
view # => App.ItemsIndexView instance

In Chrome, right-click -> "inspect element", assigns the node to $0. Then you can inspect the view with $context($0).

When you have the view, you can inspect its superview and lookup keypaths in its context:

view.get('superview')       # => Layout view
view.lookupKeypath('items') # => Batman.Set

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.