1

I'm building a simple app with a persistent view. This view is always there. The view depends on some data. Entering the application in a different state should ensure that view is present with it's data. I thought the best way to do this would be to create an initial state which calls connectOulet to connect the data and view. That way all the subsequent states have to transition through this one. I can't figure out how to get the router to automatically transition to the next state after doing the connecting.

Here is my router (this doesn't work ATM). See comments.

Inbox.Router = Ember.Router.extend
  enableLogging: true
  location: "history"
  initialState: "bootUp"

  bootUp: Ember.Route.extend
    root: Ember.Route.extend
      route: '/'
      # All states need to transition through this code
      # How can I transition to root state after this code executes?
      connectOutlets: (router, context) ->
        router.get('applicationController').connectOutlet
          outletName: "list"
          name: "messages"
          context: Inbox.store.findAll(Inbox.Message)

  root: Ember.Route.extend
    showMessage: Ember.Route.transitionTo('root.showingMessage')

    initialState: 'dashboard'

    dashboard: Ember.Route.extend
      route: '/dashboard'

    # Entering this state needs the messages view loaded
    # with data
    showingMessage: Ember.Route.extend
      route: '/:id'
      connectOutlets: (router, context) ->
        router.get('applicationController').connectOutlet
          outletName: "details"
          name: "message"
          context: context
      serialize: (router, context) ->
        id: context.get('id')
      deserialize: (router, urlParams) ->
        Inbox.store.find Inbox.Message, urlParams.id

Modeling this behavior with a FSM seems correct to me. Is this the correct way to do such a thing or is there a better way?

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
ahawkins
  • 1,164
  • 1
  • 10
  • 15
  • The first impression is that it does not have a root node. You can only have one root with all other children nested below it. Both bootup and root states are at root level – dagda1 Nov 07 '12 at 21:35

2 Answers2

1

The solution is to create a state root state which things transition through. The root state itself it not routable. So we have to create a substate for this. Here is my router.

# Assume users enters a /

Inbox.Router = Ember.Router.extend
  enableLogging: true
  location: "history"

  # Root application state
  root: Ember.Route.extend

    # This is the state that the others must transition.
    # It's route is "/". It has a nested state called "home"
    # which route is "/". Home's route is relative to "/". 
    # So when a user enters at "/" the "home" state is selected.
    # The router transitions into "index" then "home".
    # When the user enters at "/:id" the user transitions through "index"
    # since "/:id" is a subroute of "/".
    # 
    # This is explained in the router's nested state documentation.
    index: Ember.Route.extend
      route: '/'
      connectOutlets: (router, context) ->
        router.get('applicationController').connectOutlet
          outletName: "list"
          name: "messages"
          context: Inbox.store.findAll(Inbox.Message)
        router.get('applicationController').connectOutlet
          outletName: "details"
          name: "message"
        router.get('applicationController').connectOutlet
          outletName: "filters"
          controller: router.messagesController
          viewClass: Inbox.FiltersView

      showMessage: Ember.Route.transitionTo('showingMessage')

      home: Ember.Route.extend
        route: '/'

      showingMessage: Ember.Route.extend
        route: '/:id'
        connectOutlets: (router, context) ->
          router.get('messageController').set('content', context)
        serialize: (router, context) ->
          id: context.get('id')
        deserialize: (router, urlParams) ->
          Inbox.store.find Inbox.Message, urlParams.id
ahawkins
  • 1,164
  • 1
  • 10
  • 15
0

You should just be able to call connectOutlets in the root Route. I don't think you can create route/states above or before root like your example.

root: Ember.Route.extend
showMessage: Ember.Route.transitionTo('root.showingMessage')
initialState: 'dashboard'

connectOutlets: (router) ->
  router.get('applicationController').connectOutlet
    outletName: "list"
    name: "messages"
    context: Inbox.store.findAll(Inbox.Message)

dashboard: Ember.Route.extend
  route: '/dashboard'

# Entering this state needs the messages view loaded
# with data
showingMessage: Ember.Route.extend
  route: '/:id'
  connectOutlets: (router, context) ->
    router.get('applicationController').connectOutlet
      outletName: "details"
      name: "message"
      context: context
  serialize: (router, context) ->
    id: context.get('id')
  deserialize: (router, urlParams) ->
    Inbox.store.find Inbox.Message, urlParams.id
Drew P
  • 21
  • 3
  • I've posted my solution. The `root` state is "not routable" according to the documentation. I tried to call `connectOutlet` but the controllers weren't defined yet. I assume this is because of the "not routable" comment. I'm not sure what this means. Either way, my answer works as I'd like. – ahawkins Nov 14 '12 at 22:51