Controllers handle non-persisted logic related to a specific piece of UI. They typically wrap a model or an array of models. You can put functions, properties, and observers on controllers. They function much like normal Ember Objects with a couple of exceptions.
First we’ll look at the three different types of controllers.
Ember provides you with three types of controllers: ObjectController
, ArrayController
, and Controller
. You use ObjectController
whenever that controller’s route fetches a single model. Use ArrayController
when the route fetches an array of models. And finally use Controller
when the route isn’t fetching any models at all.
Controllers don’t have any specific hooks that are called upon entering them. You can use init
if you really need to, but you shouldn’t. All setup work for a controller should be done in the route, usually in the route’s setupController
hook.
So what’s left? Properties, observers, and functions. These are your bread and butter.
# app/assets/javascripts/controllers/user.js.coffee App.UserController = Ember.ObjectController.extend someFunction: -> alert('so functional') someProperty: ( -> if @get('model.firstName') is "Gregory" "Hey Gregory" else "Hey, you're not Gregory" ).property('model.firstName') someObserver: ( -> alert "You changed your name? I don't really see you as a #{@get('model.firstName')}." ).observes('model.firstName')
// app/assets/javascripts/controllers/user.js App.UserController = Ember.ObjectController.extend({ someFunction: function() { alert('so functional') }, someProperty: function() { if (this.get('model.firstName') == "Gregory") { return "Hey Gregory" } else { return "Hey, you're not Gregory" } }.property('model.firstName'), someObserver: function() { alert("You changed your name? I don't really see you as a " + this.get('model.firstName')); }.observes('model.firstName') })
You can put as many of these as you like in your controller. Any controller properties will be available to the template and view.
If you find yourself duplicating a lot of logic you can extract your code to an Ember.Mixin
and have your controller extend it like so:
# app/assets/javascripts/mixins/excited.js.coffee App.Excited = Ember.Mixin.create levelOfExcitement: "I'm so freaking excited right now!!!" # app/assets/javascripts/controllers/user.js.coffee App.UserController = Ember.ObjectController.extend App.Excited, # your controller code
// app/assets/javascripts/mixins/excited.js App.Excited = Ember.Mixin.create({ levelOfExcitement: "I'm so freaking excited right now!!!" }) // app/assets/javascripts/controllers/user.js App.UserController = Ember.ObjectController.extend(App.Excited, { // your controller code })
Now UserController
would have the levelOfExcitement
property. Also notice that mixins are created with .create
rather than .extend
.
Another major use for controllers is handling actions from templates. For example, a template may have a submit button or a delete link. These actions would be handled like so:
# app/assets/javascripts/controllers/user.js.coffee App.UserController = Ember.ObjectController.extend actions: deleteUser: -> @get('model').destroyRecord() saveChanges: -> @get('model').save()
// app/assets/javascripts/controllers/user.js App.UserController = Ember.ObjectController.extend({ actions: { deleteUser: function() { this.get('model').destroyRecord() }, saveChanges: function() { this.get('model').save() } } })
All action handlers must go inside an actions
object in the controller. This is an Ember convention to help keep your code organized.