Composer.js
- Start
- Class system
- Eventing
- Utilities
- Base
- Model
- Collection
- Controller
- Controller xdom
- Relational model
- Filter collection
- List controller
- Router
- Best practices
- Building/load order
- Tests
Controller
The controller is the piece that ties your view (generally HTML rendered in a browser) to your models/collections.
It’s main function is to listen to events from both the models (updating the view according to new data) and to the view (clicks, form posts, etc). It is the piece that coordinates between your view (the DOM) and your data layer (your models).
It also provides a handful of utilities to make rendering views and cleaning things up a bit easier.
Note: Composer doesn’t actually have a templating engine. You are free to use any engine you wish, or none at all (hand-made HTML strings).
Events
These are the event(s) fired by controllers.
release
Triggered when a controller is released (removed from the view). Arguments passed:
- the controller being released
Composer.Controller
The main controller class. Extends Composer.Base, giving it access to all of Base’s abilities.
el :: attribute(false)
A param holding the current DOM element the controller is attached to. This is the element the controller renders into and removes when it is released.
If this param is a string, it is assumed to be a selector and that element is used as the el. If not found, a new element of type tag is created.
inject :: attribute(false)
A param holding a selector (or element) that we want to inject the controller’s main element into on creation.
tag :: attribute(“div”)
The type of tag that el will be created as. For
instance, if the controller was to describe an item in a list, you might set
tag
to be “li”.
class_name :: attribute(false)
If present, sets this.el.className
on initialization, providing an easy way to
give a CSS classname to the controller’s main element.
elements :: attribute({})
An object that provides selector -> attribute mapping. Note that the elements found by the selectors are searched for within the el element and are updated after calling html.
events :: attribute({})
An object that provides event monitoring for elements within el. It sets
up events in ‘
initialize :: function(params, options)
Controller constructor. Don’t extend unless you know what you’re doing (use init) instead.
params
is a collection of parameters to set (top-level) into the controller.
For instance you can choose your el or inject selector here.
options
can contain the following items:
clean_injection
- If true, will clear the object that contains the controller’s el before injecting the el. Otherwise (the default) is to append the controller into the container (at the end).
init :: function()
Per-controller initialization function. Gets run on each controller instantiation. Override me!
render :: function()
Your controller’s render function. This function’s purpose is to generate the view for your controller and update it (probably using html). Override me!
html :: function(element_or_string, options)
Update the controller’s el’s inner HTML. This also refreshes the controller’s elements, making sure they reflect the elements in the passed HTML.
See render for example usage.
Also see the xdom documentation for an overview of how to make
html
much faster and easier to use. Composer’s xdom system runs patches
against the DOM instead of completely replacing it (like html
does by default)
which can make managing your views much, much easier.
Note that this function can take document fragments as of v1.1.12.
For an overview of what options
can contain, check out the html() section
of the xdom docs.
with_bind :: function(object, ev, fn, name)
This function wraps object
’s bind and tracks
the binding internally in the controller. When release is called
on the controller, all the bindings created with with_bind
are unbound
automatically.
This is mainly to alleviate a common pattern of having to do manually clean up bound events in a custom release function. When your controller binds to events on, say, a model, it previously had to remember to unbind the event otherwise the controller would never be garbage collected (even after all references to it are gone from your app) because the model still holds a reference to its function(s) that were bound.
Note: object
s passed to with_bind
must extend Composer.event.
Here’s an example of the traditional way of binding/cleaning up:
Here’s how it works now:
with_bind_once :: function(object, ev, fn, name)
This function is exactly like with_bind, except that instead of
calling object.bind
, it calls object.bind_once
. This lets you add one-time
events on any object that extends Composer.Event
without worrying about cleaning them up if your controller is released.
See with_bind for full usage examples.
Note: object
s passed to with_bind_once
must extend Composer.Event.
sub :: function(name, [create_fn])
A common pattern is for a controller to have one or more subcontrollers. So you may have a Dashboard controller and it could have a UserList controller and a RecentComments controller.
When the Dashboard controller releases, you want it to release its
subcontrollers automatically. sub
does this for you! It keeps
track of subcontrollers you are using and frees them on release.
name
is the (string) name you wish to give your subcontroller. It must be
unique from other subcontrollers you’re tracking. This is because the name is
used to release and re-create the subcontroller if it already exists.
create_fn
is a function of zero arguments that must return a controller
instance. This function is where you create, set up, and return your
subcontroller.
If you omit create_fn
, sub
will return the controller stored under name
.
Note that sub
will check if a controller is already stored
under the given name
. If one exists, it is released and removed from tracking
before the new one is put into its place. This is very useful in situations
where your master controller re-creates its subcontrollers on render
and you don’t want to have to worry about dangling controllers not being cleaned
up. subs
handles everything for you.
In the above, DashboardController
will automatically clean its
UserListController
subcontroller each time it renders (or when it’s released)
so you can focus on building your app and not a bunch of boilerplate cleanup BS.
remove :: function(name, options)
Recently used sub? Use
remove
is a helper function that removes and releases a tracked
subcontroller by the name given in the call to sub
. It allows
you to manually untrack and release a subcontroller without having to pull it
out via sub and check if it exists.
options
can contain the following items:
skip_release
- If true, remove the subcontroller from the parent’s tracking without releasing it. There are very few cases where this would ever be needed.
release :: function(options)
Remove the controller from the DOM (removes el) and perform any cleanup needed (such as unbinding events bound using with_bind).
Fires the release event.
Note that options
can contain silencing directives.
See the events section for a release example.
replace :: function(element)
Replace the controller’s el with another DOM element. Once the replace is complete, the elements and events are refreshed for the controller.
Composer.find_parent :: function(selector, element)
This is a utility for (recursively) finding the first parent of element
that
matches the selector
. If element
matches selector
, it is returned without
grabbing any parent elements.
For instance, if you bind an event to an <a> element but there
is an image/button/etc inside of the <a>, often times when the event comes
through, event.target
will be the image/button/etc instead of the <a>
element. In that case, you’d use find_parent
to grab the correct element: