Skip to content

Event Binding Helpers in Luca.js

datapimp edited this page Jul 9, 2012 · 1 revision

Luca provides a number of configuration API for its components which facilitate the binding of a component's methods to events that occur on instances of the CollectionManager and Application objects.

For Luca.core.Container classes there is also a component events binding API that allows you to declare in your container which events to listen for on that container's components

Auto Context Binding For Event Handlers

By setting the @bindAllEvents property to true on your prototype definitions, all event handler methods on your view will automatically be bound to the context of the view.

  _.def('MyApp.views.AutoBoundView').extends('Luca.View').with
    bindAllEvents: true
    events:
      "click a.btn" : "clickHandler"
      "click a.btn.btn-danger" : "dangerHandler"
    initialize:()->
      # You no longer need to do this
      # if you want to have these handlers run
      # in the context of this view
      _.bindAll @, "clickHandler", "dangerHandler"

Collection Manager Event Binding

Luca Applications which use the Luca.CollectionManager have the benefit of a declarative event binding syntax which allows you bind to events on collections by their name. This saves you from having to create a reference to the collection in some method, and setup a callback binding. By simply providing a @collectionEvents configuration property on your views, you can eliminate a lot of boilerplate in your components.

The format of the @collectionEvents hash is a key which is made up of the collection's name and the event separated by a space, and either a function or a name of a method on your view.

  SamplesCollection = Backbone.Collection.extend
    name: "samples"
    url: "/api/v1/samples"

  _.def("MyView").extends("Luca.View").with
    # NOTE: you may omit this property and
    # it will use Luca.CollectionManager.get() to 
    # get the main instance.
    collectionManager: "main"

    collectionEvents:
      "samples reset" : "samplesResetHandler"

    samplesResetHandler: (collection)->
      if collection.length > 1
        @doSomething() 

Application Event Binding

Similar to the CollectionManager event binding API, there is a similar API for binding to the global application object. Most applications will have a single application instance, that is either available on the global object or through a call to Luca.getApplication().

It is in the Application instance that global state tracking should occur. Should your views want to respond to changes in global application state, you can provide an @applicationEvents configuration property. The format is a key value pair, where the key represents the event being triggered by the application, and the value is a name of a method on your view or an anonymous function.

  App = new Luca.Application
    name: "main"

    defaultState:
      currentMode: "solid"

  _.def("AppBoundView").extends("Luca.View").with
    # NOTE: you may omit this and it will use Luca.getApplication()
    app: "main"

    applicationEvents:
      "change:currentMode" : "modeChangeHandler"

    modeChangeHandler: ()->
      @doSomething()

Luca.core.Container Component Events

Containers are special views whose only purpose is to render multiple components in a specified configuration, and handle all of the communication between the components. This is what allows Luca components to be extremely re-usable, because they never know about views that exist outside of them.

By providing a @componentEvents configuration property on your container, you can bind to events on the components in your container and relay information about them to other members of the container. The format is a key value pair where the key is a string which contains the name of the component and the event it triggers, separated by a space. The value is a name of a method on your view or an anonymous function.

  # ctype = component_one
  _.def("ComponentOne").extends("Luca.View").with
    name:"one"
    eventHandler: ()->
      @trigger "custom:event"

  # ctype = component_two
  _.def("ComponentTwo").extends("ComponentOne").with
    name:"two"
    eventHandler: ()->
      @trigger "some:other:event"

  _.def("MyContainer").extends("Luca.core.Container").with
    components:["component_two","component_one"]
    componentEvents:
      "one custom:event" : "customEventHandler"

    # when component named one fires an event
    # we can handle it here, pass it to two, whatever
    customEventHandler: ()->
      Luca('two').eventHandler()