Uirouter 1.0.0 Beta.2

UI-Router is rapidly approching approaching a final release of 1.0.0. This beta.2 release addresses many issues reported against AngularJS. It adds essential support for the latest version of Angular (2+).

Full changelog

AngularJS Tutorials

Angular (2+) Tutorials

New Features

In addition to fixes, beta.2 introduces many exciting features.

Lazy Loading/Future States

Lazy loading of states is now officially supported using “Future States”. Future states are a concept borrowed from UI-Router Extras for legacy UI-Router

A future state is a temporary placeholder state. When the full state is finally loaded, the placeholder is replaced with the full state.

Temporary future states only have a name, a url, and a lazyLoad function which promises to lazy load the state.

Note: a future state can be responsible for loading a single full state that will replace the placeholder. However, a future state can act as a placeholder for an entire tree of states, which are all loaded by the future state’s lazyLoad function.

When a transition to a future state is initiated, the transition is paused and the lazyLoad function is invoked. Once the code has been loaded, the lazy load hook will retry the original transition.


If we wanted to lazy load the Contacts feature, we can register a future state:

let futureContactsState = {
  name: 'contacts',
  url: '/contacts',
  lazyLoad: () => System.import('./contacts.module')
}

The contacts.module.js file (or bundle) and its required/imported dependencies loads all feature’s code. This should include states, services, components, etc.

The lazy loading hook is framework agnostic. For AngularJS, we recommend using ocLazyLoad. Angular (2+) lazy loading occurs via NgModule. The details are outlined below.

Look for a full guide on lazy loading in the near future.

State deregistration

If you need to remove previously registered states for any reason, you can now deregister them using `StateRegistry.deregister

New Angular (2+) Features

NgModule

In beta.2, we added support for the new NgModule system in Angular (2+).0.0-rc.5+.

UIRouterModule

We recommend creating modules for each application feature, which often involves a tree of states. To define a UI-Router Module, use the special @UIRouterModule decorator (instead of @NgModule).

A module created with @UIRouterModule acts just like a module created with @NgModule, but has some additions.

  • The @UIRouterModule decorator provides DI tokens for the UI-Router Services (such as StateService and TransitionService).
  • It enables the UI-Router directives for other components in the module.
  • It allows the module to declare its states.
  • It enables automatic registration of states at bootstrap and lazy load (no need for INITIAL_STATES.forEach(state => stateRegistry.register(state)).
  • It adds any routed components (from the states array) to the declarations: and entryComponents: lists, so they will be compiled and available.
@UIRouterModule({
  states: [ contactsState, contactsListState, contactsDetailState ]
})
class MyFeatureModule {}

Bootstrapping

The root module should provide UIRouter itself using [provideUIRouter]( The UIRouter Config class may be supplied using the first argument.

@UIRouterModule({
  imports: [BrowserModule],
  providers: [
      provideUIRouter({ configClass: MyUIRouterConfigClass })
  ],
  states: [homeState]
})
class RootAppModule {}

Lazy loading

A UIRouterModule can also be lazy loaded using the new “Future State” feature. Create a placeholder state with a lazyLoad property which uses the loadNgModule lazy load helper.

let futureContactsState = {
  name: 'contacts',
  url: '/contacts',
  lazyLoad: loadNgModule('./contacts.module')
}

Then, define ContactsModule in contacts.module.ts and export it as default.

@UIRouterModule({
  states: [ contactsState, contactsListState, contactsDetailState ]
})
export default class ContactsModule {};

Provide an implementation of the NgModuleFactoryLoader which knows how to load the NgModuleFactory. Angular supplies a factory load for SystemJS: SystemJsNgModuleLoader

@UIRouterModule({
  imports: [BrowserModule],
  providers: [
      provideUIRouter({ configClass: MyUIRouterConfigClass }),
      { provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader }
  ],
  states: [homeState]
})
class RootAppModule {}

Although Angular does not provide other NgModuleFactoryLoaders, they are horribly difficult to create. Read the source code for the SystemJSNgModuleLoader to learn how. I expect other loaders to appear in the wild soon, or additional blessed loaders (i.e., for webpack) from the Angular team.


Angular (2+) users should look over:

Rx / Observables

In beta.2, we also added initial support for a reactive approach to UI-Router apps. We added four observables to UIRouterGlobals to monitor the state of the router.

  • states$: An Observable<StatesChangedEvent>. Subscribers are notified of state registration and deregistration.
  • start$: An Observable<Transition>: Subscribers are notified when a new transition starts.
  • success$: An Observable<Transition>: Subscribers are notified when a new transition finishes successfully.
  • params$: An Observable<{ [paramName: string]: any }>: Subscribers are notified of the parameters of the latest successful transition.

These observables will be released as a separate project, Reactive Extensions for UI-Router. The rx extensions are currently a work in progress. They will be maintained separately and will work with any UI-Router (like AngularJS and React).

UI-Router for Angular (2+) will always have the reactive extensions by default.

AngularJS + Angular (2+) Hybrid

The ng1-to-ng2 hybrid adapter has been updated for Angular (2+) rc.5 and ui-router 1.0.0-beta.2. AngularJS/Angular (2+) hybrid users should look over the recent changes to https://github.com/ui-router/sample-app-ng1-to-ng2

Note: Due to an apparent bug in rc.6, ng1-to-ng2 users MUST stick to rc.5 for now.

Updated:

Leave a Comment