UI-Router Sample App

Explore the Sample App for:

UI-Router 1.0 Sample Application

The sample app is intended to demonstrate a non-trivial ui-router application. It models the following

  • Multiple application feature modules
  • Authentication (simulated)
  • Authenticated and unauthenticated states
  • State lifecycle management
  • Application data retrieval
  • REST data retrieval (simulated)

Visualizer

We’re using the State and Transition Visualizer to visually represent the current state tree, as well as the transitions between states. Explore how transitions work by hovering over them, and clicking to expand details (params and resolves).

Note how states are entered when they were previously not active, exited and re-_entered_ when parameters change, and how parent states whose parameters did not change are retained.
Each of these (exited, entered, retained) correspond to a Transition Hook.

Structure

The application utilizes ES6 modules.

There are many ways to structure a ui-router app. We aren’t super opinionated on application structure. Use what works for you. We organized ours in the following way:

  • Sub-module (feature) organization
    • Each feature gets its own directory.
    • Features contain state definitions, components, and other code such as services.
  • Leverage ES6 modules
    • Each thing (component, state, service) is defined in its own file (ES6 module) and is exported.
    • Each feature module has an index file which imports the code, and composes them together (as the feature module), then re-exports them.
    • At the top level, the bootstrap imports all the features and composes the application, registering services and states with UI-Router, etc.

UI-Router Patterns

  • Default substate for a top-level state
    • Example: the mymessages state specifies redirectTo: 'mymessages.folder'. When the user tries to activate mymessages (e.g., using a ui-sref link or a bookmark), the transition is redirected to mymessages.folder.
  • Defining a default parameter for a state
    • Example: the folderId parameter of the folder state defaults to a value of ‘inbox’.
  • Application data lifecycle (resolve)
    • Data loading is managed by the state declaration, via the resolve: block
    • Data is fetched before the state is entered
    • Data is fetched according to state parameters
    • The state is entered when the data is ready
    • The resolved data is provided to the components
    • The resolve data is accessible until the state is exited
  • Data dirty checking and confirmation hooks
    • Example: The contacts.edit state allows a user to edit contact details using a form. If a user has modified data in the form, then tries to activate a different state, the edit contact component will prompt for confirmation before allowing the transition to exit contacts.edit.
  • Custom application behaviors using declarative Transition Hooks.
    • The authRequired hook checks for state metadata, which declares that a state requires authentication. When a transition starts, the inspects the destination state’s data.authRequired: true property. If it’s truthy, then it checks that the user is authenticated, or redirects to the login state.