Shopify/batman — pull request #534 by brentd (2012-08-20 22:37:44+00:00)
Title: Set 'view' as a property during Batman.Controller::render

Make `view` an observable property on controllers, so that we can more easily bind to view lifecycle events when subclassing `Batman.View` isn't ideal.

Here's some simplified example code of what brought me to this:

```coffee
class App.ProductsController extends Batman.Controller
routingKey: 'products'

@::observe 'view', (view) ->
view.on 'beforeAppear', @fadeInWhenLoaded

fadeInWhenLoaded: (node) =>
$(node).hide()
@once 'loaded', -> $(node).fadeIn()

index: ->
@set 'products', App.Product.get('loaded')
App.Product.load => @fire 'loaded'

show: (params) ->
@set 'products', App.Product.find params.id, (err) =>
throw err if err
@fire 'loaded'
```

The idea is to allow the controller to hold off on displaying the view until network dependencies are satisfied. This example just fades in the view, but it could be more sophisticated with a loading graphic, etc. This example is also simplistic in that it doesn't account for multiple network dependencies.

This could also be accomplished by overriding `render()`, modifying the returned view from `super`, but I feel like overriding methods is something that should be avoided when better mechanisms like event binding is available.

I realize I could have simply bound the view templates to a `'loaded'` property with `data-showif` and an animation mixin, but that felt repetitive. Even if that's the preferred approach, I don't feel like observing the view property is such an outlandish thing to want to do.

Open to your thoughts, though.

BTW, it might be interesting if in the event system allowed `@::on 'view.beforeAppear', -> ...`, where the event is a keypath with the last segment being the actual event. As `view` changes, the event is rebound. Although this does raise the question of whether view lifecycle events should bubble up to the controller in some other way, like `-viewWillAppear`, `-viewWillDisappear` and friends in UIViewController in iOS.