Releases: angular-ui/ui-router
legacy maintenance release
(2016-05-14) diff
This is a release of the legacy
branch, primarily to fix the $scope destroy ordering issues introduced in 0.2.16, as well as adding $scope.$resolve
to enable "route-to-component-template".
We recommend all users to try the 1.0.0 alpha and report any issues it causes with your application. Read the known breaking changes between the legacy and 1.0 branches.
BC-BREAK
In 0.2.16 we delayed the ui-view $scope destroy() until after all animations were completed. This was a mistake, and we're reverting it in 0.3.0.
The original issue that we tried to address: #1643
We are switching back to 0.2.15 behavior. The scope is now destroyed as soon as the view is swapped out. This allows cleanup to happen in response
to the $destroy event. If you need to do things after the animation, we've put the promise on the element.data('$uiView')
in #2562
Bug Fixes
- state: Inject $state at runtime to force initialization (de3a04a7, closes #2574)
- ui-sref: update ui-sref-active/eq info when params change When ui-state dynamicly changes (9698ec4d, closes #2554)
- ui-state: update ui-sref-active/eq info when ui-state dynamicly changes watchers, make sur (abb3deba, closes #2488)
Features
-
resolve: Put resolve values on the scope as
$scope.$resolve
This enables easier "routing-to-component-template", i.e.,
.state({ name: 'foo', resolve: { thing: (MyService) => MyService.getThing() } template: '<my-component component-input="$resolve.thing"></my-component>' });
-
uiView:
1.0.0-alpha.5
(2016-05-12) diff
Features
ng2
- ng2.uiView: bind resolve data to input[] and @Input(), process bindings:(f6dae28)
- ng2.urlRouter: HTML5 PushState support(9842fb7), closes #2688
- ng2.UIRouter: update to ng2 beta.17(45c0758)
- ng2.UIRouter: Update ui-router for ng2 rc.1(3219406), closes #2722
Bug Fixes
ng1
- ng1.component: Allow route-to-component "@" and optional bindings(71b3393), closes #2708
- view: only run ng1 route-to-component code if component: is a string(ec1c534)
ng2
- ng2.uiSrefStatus: Avoid "dehydrated detector" error(9111727), closes #2684
- ng2.uiView: Fix "Invalid left-hand in assignment"(3f711a1)
- build: declare external dep on
angular/core
in webpack bundle(adfbde3), closes #2687
Core
- attachRoute: Do not update URL after syncing from url(8742511), closes #2730
- common: only use window if available(32ff988)
- coreservices: Use Promise.reject()/resolve()/all()(62b2ebc), closes #2683
- paramTypes.hash: Update hash for each transition(79d4fd7), closes #2742
- Rejection: Dont log an ignored trans as console.error(7522c26), closes #2676
- resolve: Fix regression; Allow resolve values to be service names(a34fd3b), closes #2588
- StateQueueManager: Do not throw on orphan states.(95ae0cf), closes #2546
- TransitionManager: Update url even when the Transition is ignored.(f9c3e3c), closes #2723
1.0.0-alpha.4
(2016-04-06) diff
1.0.0-alpha.3
(2016-04-03) diff
Note: 1.0.0-alpha.2 and 1.0.0-alpha.3 are identical.
Angular 2
This is the first UI-Router release with angular 2 support.
See quickstart-ng2 for a small ui-router-ng2 app
The first pass at ng2 docs may be found here
NG2 support is a work in progress.
In particular, only hashbang routing is supported at the moment.
Also, injecting resolves and transition hooks is currently only possible using the angular1 style string-based injection. Any global providers that you want injected into a resolve or hook should be mapped to a string. See this example for how to do that.
Bug Fixes
- ViewHooks: Avoid calling $onInit if angular 1.5 will call it for us (d42b617), closes #2660
- ViewHooks: Fix problem with injecting uiCanExit (76ab22d), closes #2661
- view: temporary sanity check that a node exists (1c0edeb), closes #2657
- justjs.$q: Fix $q.all([..]) and $q.all({...}) (b1624c6)
- ng2.uiSref: Fix anchor href generation (98b5b42)
- ng2.uiSrefStatus: calculate target state parameters (46cdf4c)
- ng2.uiView: Dispose prev comp on empty viewconfig (f28e0c3)
Features
1.0.0-alpha.1
(2016-03-27) diff
This release checkpoints the continued development of the 1.0 codebase, as we approach final release.
Notable additions in this release:
Packages
We are now publishing three separate packages using a new publishing architecture:
ui-router-core
(npm)angular-ui-router
(npm and bower)ui-router-ng2
(npm; coming soon, in 1.0.0-alpha.2)
The ui-router-core
package is framework-agnostic. Both ng1 and ng2 packages share the code in ui-router-core
and provide viewport adapters to implement the <ui-view>
. Third parties could potentially depend on ui-router-core
to implement ui-router adapter for any other framework.
Route to component
We now support routing to angular 1.5+ .component()
s in two different ways. We now put the resolved data on $scope.$resolve
(or $scope[controllerAs]$resolve
), so you can use Components as route templates in the same way as ngRoute.
We also now allow a state's view to be specified using component: 'MyComponent'
in lieu of a controller+template. We will map resolve data to the component's bindings:
by name.
See the component and bindings for more information.
We also support angular 1.3+ .component()
with Todd Motto's polyfill, and even support old school angular 1.2 directives (instead of bindings: { foo: '<' }
, we will map to scope: { foo: '=' }
).
View hooks (component/controller hooks)
For a long time, we've advocated using the state machine to manage application lifecycle. However, using callbacks such as onExit
can be challenging, since the answer to "can I exit this state?" often lives in the view. We've introduced some view-level callbacks that can be used to integrate controller code with the transition pipeline.
The first view hook we've implemented is uiCanExit()
. This hook can be used much the same as the component router's routerCanDeactivate
. See the Ng1Controller docs for more information. The uiCanExit
view hook is simply sugar for adding a transition onBefore hook.
Dynamic params
Dynamic parameters (the replacement for reloadOnSearch
) can be declared in a params block in a state definition like so: params; { fooParam: { dynamic: true } }
. When a dynamic parameter changes, it does not cause the state to be reloaded. A controller/component callback uiOnParamsChanged
may be used to be notified of parameter changes.
See the Ng1Controller docs for details on the new callback.
Expose internal state object's API
We're now exposing the internal state objects via an undocumented API. This can be useful for other library authors who need access to things like .parent
or .includes
. This internal API is subject to change (it hasn't changed much so far), so be careful. The internal api of an arbitrary state can be fetched like so:
var normalState = $state.get('foo');
var internalStateObject = normalState.$$state();
console.log(internalStateObject.parent.name);
We will maintain a list of Known BC from 0.2.x to 1.0 final to help you upgrade to the 1.0 release.
Bug fixes and features since 1.0.0alpha0
Bug Fixes
- date: Compare dates only using year, month, date (7a68ade), closes #2484
- params: Clone all properties of a Node. Introduce applyRawParams() (88c624d)
- RejectFactory: stringify rejections with circular dependency-aware stringify (199db79), closes #2538
- src/resolve: use injector's strictDi value in calls to .annotate (4c5b5d8)
- stateQueueManager: Use
location: true
for url-matched transitions (25e0c04), closes #2455 - stateService: Process reload: in the StateService.target() (081da32), closes #2537
- Transition: Do not reuse resolves for reloaded state during redirect (0c123c3), closes #2539
- Transition: Reject Transition promise when onBefore error (4b6d56f), closes #2561
- Transition: Reset URL to current state after aborted transition (3a1308b), closes #2611
- transition/transitionService: uses console.error to log error in default error handler (43a8fc5)
- ui-sref: update ui-sref-active/eq info when params change (dcbaebf), closes #2554
- ui-state: update ui-sref-active/eq info (025ebc8), closes #2488
- UrlMatcher: Format parent/child UrlMatchers properly (86e07ef), closes ##2504
- UrlMatcher: isOptional always false for empty parameter (4e85db4)
Features
- params: Add uiOnParamsChanged controller callback (961c96d), closes #2608 #2470 #2391 #1967
- resolve: Allow all resolved data for a node to be injected as
$resolve$
(e432c27) - state: Expose the internal state API via
$$state()
(92053f1), closes #13 - ui-router-ng2: Initial angular2 support (217de70)
- uiCanExit: Add controller lifecycle hook "uiCanExit" (afcfe95)
- uiView: Expose the resolved data for a state as $scope.$resolve (0f6aea6), closes #2175 #2547
- uiView: Fire the $onInit hook (c8afc38), closes #2559
- uiView: Put $animate promises on element.data('$uiView') (a5578de), closes #2562 #2579
- view: Route a view to a directive using
component:
(1552032), closes #2627
Other commits
Many of these commits are merged from 0.2.x legacy
branch
- uiSrefActive: allow multiple classes (120d7ad), closes #2481 #2482
- justjs: provide naive implementation of most of the coreservices api (426f134)
- resolve: add $resolve service back to 1.0 (70c6659)
- uiSrefActive: allow active & active-eq on same element (d9a676b), closes #1997
- uiSrefActive: provide a ng-{class,style} like interface (a9ff6fe), closes #1431
- uiSrefActive: Added support for multiple nested uiSref directives (b184494)
- uiState: add ui-state directive (3831af1), closes #395 #900 #1932
- urlMatcher: add support for optional spaces (4b7f304...
0.2.18
(2016-02-07) diff
This is a maintenance release which fixes a few known bugs introduced in 0.2.16.
Bug Fixes
- $urlRouter: revert BC: resolve clashing of routes This reverts commit b5c57c8 (2f1ebefc, closes #2501) This reverts ordering of url matching rules to the 0.2.15 behavior: rules are once again matched in the order they were registered.
- uiState: Corrected typo for 'ref' variable (#2488, #2508) (b8f3c144)
- $urlMatcherFactory: Fix to make the YUI Javascript compressor work (ad9c41d2)
- stateBuilder: fix non-url params on a state without a url. (d6d8c332, closes #2025)
- ui-view: (ui-view) use static renderer when no animation is present for a ui-view (2523bbdb, closes #2485). This allows a ui-view scope to be destroyed when switching states, before the next view is initialized.
Features
0.2.17
(2016-01-25) diff
This release addresses a regression in uiSrefActive
when using multiple classes. While we'll continue to address any serious issues on the 0.2.x branch, we strongly urge everyone to begin the process of migrating to 1.0, and providing feedback on any regressions. We're committed to providing everyone with a smooth transition process. You can read about migrating here. Thanks!
0.2.16
(2016-01-24) diff
We hope this is the final release of the 0.2.x series (edit: nope). All development effort will now be focused on the upcoming 1.0 release.
Bug Fixes
- $state:
- statechangeCancel: Avoid infinite digest in .otherwise/redirect case. Don't clobber url if a new transition has started. Closes #222 (e00aa695, closes #2238)
- transitionTo: Allow hash (#) value to be read as toParams['#'] in events. Re-add the saved hash before broadcasting $stateChangeStart event. (8c1bf30d)
- $stateParams: Fix for testing: reset service instance between tests (2aeb0c4b)
- $urlRouter:
- UrlMatcher:
- Properly encode/decode slashes in parameters Closes #2172 Closes #2250 Closes #1 (02e98660, closes #2339)
- Array types: Fix default value for array query parameters. Pass empty arrays through in handler. (20d6e243, closes #2222)
- Remove trailing slash, if parameter is optional and was squashed from URL (77fa11bf, closes #1902)
- Allow a parameter declaration to configure the parameter type by name. closes #2294 (e4010249)
- include the slash when recognizing squashed params in url (b5130bb1, closes #2064)
- Allow url query param names to contain periods (d31b3337)
- reloadOnSearch: Update
locals.globals.$stateParams
when reloadOnSearch=false (350d3e87, closes #2356) - ui-view:
- uiSref:
Features
- $IncludedByStateFilter: add parameters to $IncludedByStateFilter (963f6e71, closes #1735)
- isStateFilter: Include optional state params. (71d74699)
- $state: make state data inheritance prototypical (c4fec8c7)
- $stateChangeStart: Add options to event (a1f07559)
- UrlMatcher: Add param only type names (6a371f9b)
- uiSrefActive:
- uiState: add ui-state directive (3831af1d, closes #395, #900, #1932)
- urlMatcher: add support for optional spaces in params (4b7f3046)
Happy New Year
After a great deal of thought, hard work, and a lot of feedback and support from the community, the AngularUI Router team is proud to announce the first alpha release of UI Router 1.0. It is the culmination of a complete rewrite of the internal architecture of the 0.2.x series (as well as a port to TypeScript), which began over 18 months ago, and has resulted in a more robust, more flexible design, which addresses many of our community’s biggest requests and most pressing concerns.
Backwards Compatibility
Despite the massive refactor, we've managed to retain almost 100% API compatibility with 0.2.x, barring a few small semantic differences:
- Return values for
onEnter
/onExit
hooks are now meaningful (see below), so if you're using CoffeeScript or defining hooks with ES6 arrow functions, add&& null
to your return expression if you don't want to opt in to any new behavior - To ease debugging for new users, certain errors that would otherwise be swallowed (i.e. in resolves) are now printed to the console by default; this can be disabled with
$transitionsProvider.defaultErrorHandler(() => {})
(see more about the new$transitions
service below) - Due to the design of the new view system, templates are required for all views
- All state events, (i.e.
$stateChange*
and friends) are deprecated and disabled by default; re-enable them by including theng1/stateEvents.js
file, and depend on theui.router.state.events
angular module in your application.
New Features
The refactor has also enabled a number of important new features:
Transition hooks
http://angular-ui.github.io/ui-router/feature-1.0/interfaces/transition.ihookregistry.html
Internally, the state transition system is now implemented as a highly-configurable pipeline of operations and dependent relationships. This pipeline exposes a number of hook points that provide much more flexibility over the previous event-driven architecture.
The hooks system interface allows application code to be much more targeted around specific groups or types of transitions. Hooks have also been made more expressive by allowing meaningful return values. For example, this hook disables all transitions from children of foo
states to children of bar
states:
$transitionsProvider.onStart({ from: 'foo.*', to: 'bar.*' }, () => false);
Matching rules allow specific states to be targeted, and can target based on glob rules, as with $state.includes()
. Matching rules can also be functions, enabling patterns like the following:
$transitionsProvider.onStart({
to: (state) => !!state.data.requiresAuth
}, (UserService) => UserService.current().then(() => true, () => false));
Some things to note:
- The matching rule returns the boolean value of
requiresAuth
in the state's custom data to determine whether to enforce a current user session - The paired hook function is injectable, meaning it can accept any custom services, as well as some special injectable values (see below)
- This hook function returns a promise, which will hold the transition until the promise resolves, meaning you can use this pattern for implementing flows such as prompting for auth information, then resuming the transition
- Finally, the promise returns a boolean value; returning
false
from a hook (either through a promise or directly) will cancel the transition
The Transition
pipeline has first-class support for redirecting transitions. Simply return a TargetState
from a hook using the $state.target()
factory method.
Consult the 1.0 hook documentation for the full list of hooks and where they take place within the transition pipeline.
State-specific hooks
In addition to transition-level hooks (which are equivalent in scope to $stateChange*
events), $transitionsProvider
also implements state-specific hooks, which are essentially global versions of the standard onEnter
/onExit
hooks. These fire once per state being entered or exited, and provide a $state$
injectable, representing the state object being entered or exited. These hooks allow you to implement common enter/exit logic across groups of states.
We've also introduced a new hook, onRetain
, which allows you to define how a state should behave when it is held over during a transition.
The Transition
Object
http://angular-ui.github.io/ui-router/feature-1.0/classes/transition.transition-1.html
Instead of an endless list of parameters as in the state events of 0.2.x, all transition details are now fully encapsulated in the Transition
object. You can inspect parameters, origin and destination states, resolves, and trace back transition redirections.
The Transition object allows you to add or override resolves at runtime using the addResolves()
method, the Transition object exposes the same set of hooks as $transitionsProvider
, such that hooks (e.g., onFinish()
) can be applied on a per-transition basis.
The Transition
object is available as an injectable in any hook as $transition$
.
Resolve Policies
We've made it possible to tune exactly how resolves are handled, with the following options available:
EAGER
: All eager resolves for a transition are resolved at the beginning, before any states are entered (this is way UI-Router 0.2.x handles resolves)LAZY
: Lazy resolves are resolved when the state they are declared on is entered.JIT
: Just-In-Time resolves do not resolve until just before they are injected into some other function. (extremely lazy)
In the future, this will enable powerful progressive rendering capabilities.
Sample App, State Visualizer, Transition Visualizer
We're working on a new sample app (Source), as well as a state and transition visualizer. Check them out, and give us some feedback. We'd like to make the visualizers into a Chrome Extension that you can enable on any UI-Router 1.0 app.
Why UI Router?
With the advent of Angular 2 and the Component Router, we’re often asked if UI Router still has a place in the Angular ecosystem. From what we’ve observed, we believe that the answer to that question is an unequivocal yes. While Component Router offers a number of advancements in DOM handling and lifecycle management, it still couples routes 1:1 with components.
We believe that for sophisticated applications (and even not-so-sophisticated ones), a hierarchical state machine is the best abstraction boundary, allowing application code to stay declarative, and well organized. This, among many other reasons (like typed and dynamic parameters), is why we've been hearing over and over again from enterprise users to solo developers, that UI Router support is at or near the top of their needs list for migrating their applications to Angular 2.
The Future
Our immediate goal is to collect feedback on this release so that we can make sure we're not missing any important use cases or breaking compatibility in any unintended way. To do that, we need your help. Please test UI Router against your app, and let us know if you experience any issues. Try out the new features and let us know if there's anything (not already on the roadmap) that we're still missing.
After we've shipped the final 1.0 release, we're heading back into the workshop with the following priorities:
- Angular 2 Support: Unsurprisingly, this has been our most oft-request feature of late, and by converting the codebase to TypeScript, we're already a long way towards supporting it; our goal is to support Angular 1 and 2 simultaneously, and provide people who wish to stay with UI Router a smooth (as possible) transition path
- Pipeline API: We plan to further decouple the internal transition pipeline at the core of UI Router, and implement a public API for managing it — this will enable even more sophisticated UI state handling, such as parallel transitions and multiple active states (see: 'sticky states' from UI Router Extras)
- Lazy Loading & Runtime State Tree Management: Load, add, move, and remove states and state hierarchies on the fly
- Progressive Rendering: An important mobile-first feature, it will allow much finer tuning of the user experience while waiting for dependency data to resolve
- Documentation: We've switched to TypeDoc, for documentation generation. We still have a lot of work to do to get the documentation quality back up to our standards; bear with us.
Resources
- ngPittsburgh, Sept 2015: A talk that explains UI Router's philosophy, differences from Component Router, and new features in 1.0
Acknowledgements
- First and foremost, I'd like to thank my co-conspirator, Chris Thielen, especially for being longsuffering with my perfectionism
- Wesley Cho, for kick-starting the port to TypeScript, crushing some pretty difficult bugs, and generally being a great source of intel and encouragement
- Rob Wormald, for architectural inspiration, patience for our never-ending streams of questions, and general cleverness
0.2.15
(2015-05-19) diff
This release fixes some issues reported in 0.2.14 and 0.2.13. It also fixes a long-standing issue with the broken reloadOnSearch option.
See milestone: https://github.com/angular-ui/ui-router/issues?q=milestone%3A0.2.15+is%3Aclosed
Bug Fixes
- $state: reloadOnSearch should not affect non-search param changes. (6ca0d770, closes #1079)
- urlMatcherFactory: Revert to 0.2.13 behavior where all string parameters are considered optional fi (495a02c3, closes #1963)
- urlRouter: allow .when() to redirect, even after a successful $state.go() - This partially (48aeaff6, closes #1584)
Features
- $state: Inject templateProvider with resolved values (afa20f22)