UI-Router for AngularJS
State-based routing framework for AngularJS with nested, parallel views and typed transitions.
Repository Health
Technical Analysis
UI-Router for AngularJS is the de-facto routing solution for AngularJS 1.x applications, providing flexible, nested-state-based navigation where ngRoute only offers flat URL-to-controller mappings. It models an app’s navigation as a hierarchical tree of named states, each of which can declare its own template, controller, resolved data, and URL parameters, with child states inheriting and extending their parents.
Built as an AngularJS-specific adapter over the framework-agnostic @uirouter/core engine, it adds Angular DI providers ($stateProvider, $urlRouterProvider), the ui-view/ui-sref/ui-sref-active directives, and a resolve-based async data-loading layer, letting teams maintaining legacy AngularJS 1.x codebases get nested and parallel views, typed transition hooks, and permission-gated navigation without migrating frameworks.
What You Get
- A hierarchical state machine ($stateProvider) instead of a flat URL-to-controller router
- Nested and parallel ui-view directives for rendering multiple named viewports per state
- Resolve-based async data loading that gates a transition until dependencies are ready
- Typed transition lifecycle hooks (onBefore, onStart, onSuccess, onError) for intercepting navigation
- ui-sref / ui-sref-active directives for state-aware links and active-class bindings
Common Use Cases
- Multi-step wizards sharing a parent layout while resolving step-specific data per child state
- Dashboard apps with a persistent sidebar and independently updating content panes via parallel views
- Maintaining legacy AngularJS 1.x codebases that need nested routing ngRoute never supported
- Permission-gated navigation using onBefore transition hooks combined with resolves
Under The Hood
Architecture
UI-Router for AngularJS wraps the framework-agnostic @uirouter/core package with AngularJS-specific bindings — src/index.ts re-exports core state/URL/transition services and layers on stateProvider.ts (the $stateProvider DI provider proxying to StateRegistry/StateService), directives/viewDirective.ts (implementing the ui-view directive that renders resolved templates/controllers into named viewports) and directives/stateDirectives.ts (ui-sref/ui-sref-active). Core routing logic — state-tree matching, URL parsing, transition lifecycle — lives entirely in the separate @uirouter/core peer dependency; this package’s job is purely the AngularJS 1.x DI/directive/template-binding adapter layer, evidenced by legacy/core-adapter.js and the templateFactory.ts glue code. It’s a clean adapter-pattern separation: changing core’s state machine wouldn’t touch this package’s directive code, but the two-package split adds a layer of indirection to trace.
Tech Stack
TypeScript compiled to both CommonJS and ES modules via tsc, then bundled with Rollup into four separate UMD entry variants (router, monolithic router, events, resolve). Peer dependencies are @uirouter/core (the framework-agnostic router engine) and angular itself (>=1.2.0). Testing uses Jest with ts-jest, run against six pinned AngularJS versions (1.2 through 1.7) via an NG environment variable and angular-mocks. Linting is ESLint plus @typescript-eslint, with Prettier and Husky pre-commit hooks. Distribution targets both npm and Bower.
Code Quality
Tests live under a dedicated test/ directory with one spec file per major module (state, URL router, view directive, URL matcher factory, and more) plus a separate TypeScript type-checking suite, and CI matrix-tests six AngularJS versions rather than just one. Source is fully typed TypeScript with public API surfaces documented via @publicapi/@module JSDoc tags consumed by a typedoc-based doc generator. Error handling favors explicit throws in state/URL validation paths over silent failures. GitHub Actions CI is wired and badge-linked from the README.
What Makes It Unique
UI-Router’s differentiator versus AngularJS’s built-in ngRoute is modeling navigation as a hierarchical state tree rather than a flat URL-to-controller table — states can be nested, and a single state can render multiple named or parallel views simultaneously. The resolve mechanism (per-state async dependency injection gating a transition) and typed transition hooks predate similar patterns that later routers later standardized on. It isn’t net-new by modern standards — contemporary routers offer comparable nested/typed routing — but it was genuinely influential in its era and remains the standard answer for AngularJS 1.x specifically because ngRoute never added nested-state support.