Controllers & Views • Each view is backed by a controller. • Controllers proxy the models and add client- side application state. • They need to be named xView and xController App.ApplicationView = Ember.View.extend({}) App.ApplicationController = Ember.Controller.extend({}) App.IndexView = Ember.View.extend({}) App.IndexController = Ember.Controller.extend({})
Contacts = Ember.Application.create(); Contacts.ApplicationController = Ember.Controller.extend({}); Contacts.ApplicationView = Ember.View.extend({ templateName: 'application' }) Contacts.Router = Ember.Router.extend({ location: 'hash', root: Ember.Route.extend({}) }) Contacts.initialize(); so even though it is an instance, it is uppercased
Contacts = Ember.Application.create(); Contacts.ApplicationController = Ember.Controller.extend({}); Contacts.ApplicationView = Ember.View.extend({ templateName: 'application' }) Contacts.Router = Ember.Router.extend({ location: 'hash', root: Ember.Route.extend({}) }) Contacts.initialize(); Define a route named ‘root’. This will act as a container for all other states. The router will transition to this state upon initialisation
Contacts = Ember.Application.create(); Contacts.ApplicationController = Ember.Controller.extend({}); Contacts.ApplicationView = Ember.View.extend({ templateName: 'application' }) Contacts.Router = Ember.Router.extend({ location: 'hash', root: Ember.Route.extend({}) }) Contacts.initialize(); • Initialise an instance of the router • Look through the namespace for anything named xController and initialise it as a property on the router
Contacts.get('router').toString() // Contacts.get('router.applicationController').toString() // Post initialisation An instance of the router has been created and is available on the application namespace An instance of the ApplicationController has been created and is available on the router instance
Contacts.Router = Ember.Router.extend({ location: 'hash', root: Ember.Route.extend({ index: Ember.Route.extend({ route: '/', connectOutlets: function(router){ router.get('applicationController').connectOutlet('index') } }) }) }) Add the new state Leaf states have a route property which is set to a url. When the browser url matches this url, the application will transition into this state
Contacts.Router = Ember.Router.extend({ location: 'hash', root: Ember.Route.extend({ index: Ember.Route.extend({ route: '/', connectOutlets: function(router){ router.get('applicationController').connectOutlet('index') } }) }) }) Add the new state When the application first loads, the browser will have a url of ‘/‘ and the router will transition into this state
Contacts.Router = Ember.Router.extend({ location: 'hash', root: Ember.Route.extend({ index: Ember.Route.extend({ route: '/', connectOutlets: function(router){ router.get('applicationController').connectOutlet('index') } }) }) }) Add the new state connectOutlets is a callback that gets triggered when the application transition into the state. We use the callback to plug the views into any outlets that we’ve defined in the templates.
Contacts.Router = Ember.Router.extend({ location: 'hash', root: Ember.Route.extend({ index: Ember.Route.extend({ route: '/', connectOutlets: function(router){ router.get('applicationController').connectOutlet('index') } }) }) }) Add the new state and call connectOutlet on it, passing ‘index’ as an argument
Contacts.Router = Ember.Router.extend({ location: 'hash', root: Ember.Route.extend({ index: Ember.Route.extend({ route: '/', connectOutlets: function(router){ router.get('applicationController').connectOutlet('index') } }) }) }) Add the new state ‘index’ means that an instance of IndexView will be created and plugged into the outlet. The view will be backed by the instance of IndexController that was initialised for us.
Put some links in the templates <br/><h2>Index page</h2><br/><a {{action goToShow href=true}}>Go to show</a><br/> <br/><h2>Show page</h2><br/><a {{action goToIndex href=true}}>Go to index</a><br/>
Data Ember.Object.create({ name: 'James Croft', city: 'London', //... }) Contacts are simple Ember Objects created with data pulled from the meetup.com API
Change our index template to list all the contacts <br/><ul><br/>{{#each contact in controller}}<br/><li><a {{action showContact contact href=true}}>{{contact.name}}</a></li><br/>{{/each}}<br/></ul><br/>
Change our show template to list the contact info <br/><h2>{{name}}</h2><br/><img {{bindAttr src="photo"}}/><br/><dl><br/><dt>Bio</dt><br/><dd>{{bio}}</dd><br/><dt>City</dt><br/><dd>{{city}}</dd><br/><dt>Topics</dt><br/><dd><br/><ul><br/>{{#each topic in topics}}<br/><li>{{topic}}</li><br/>{{/each}}<br/></ul><br/></dd><br/></dl><br/>
• Entering the application at a particular URL doesn’t give us access to the previously loaded data. • We need something to convert the params hash from the matched url into an object url http://localhost:3000/#/show/James Croft matches route /show/:name with params {name: 'James Croft'} We need to use our params to find our contact.
So we can replace: connectOutlets: function(router){ router.get('applicationController').connectOutlet({ name: 'index', context: Contacts.Data.all() }); } With: connectOutlets: function(router){ controller = router.get('indexController') controller.set('content', Contacts.Data.all()) view = Contacts.IndexView.create({controller: controller}) router.set('applicationController.view', view) } And it all still works.