@@ -169,6 +169,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
169
169
}
170
170
} ] ) ;
171
171
}
172
+
172
173
return state ;
173
174
}
174
175
@@ -220,6 +221,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
220
221
221
222
var TransitionSuperseded = $q . reject ( new Error ( 'transition superseded' ) ) ;
222
223
var TransitionPrevented = $q . reject ( new Error ( 'transition prevented' ) ) ;
224
+ var TransitionAborted = $q . reject ( new Error ( 'transition aborted' ) ) ;
223
225
224
226
root . locals = { resolve : null , globals : { $stateParams : { } } } ;
225
227
$state = {
@@ -238,18 +240,33 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
238
240
toParams = toParams || { } ;
239
241
options = extend ( { location : true , inherit : false , relative : null } , options ) ;
240
242
243
+ var from = $state . $current , fromParams = $state . params , fromPath = from . path ;
244
+
241
245
var toState = findState ( to , options . relative ) ;
242
246
247
+ var evt ;
248
+
243
249
if ( ! isDefined ( toState ) ) {
244
- if ( options . relative ) throw new Error ( "Could not resolve '" + to + "' from state '" + options . relative + "'" ) ;
245
- throw new Error ( "No such state '" + to + "'" ) ;
250
+ // Broadcast not found event and abort the transition if prevented
251
+ var redirect = { to : to , toParams : toParams , options : options } ;
252
+ evt = $rootScope . $broadcast ( '$stateNotFound' , redirect , from . self , fromParams ) ;
253
+ if ( evt . defaultPrevented ) return TransitionAborted ;
254
+ // Always retry once if the $stateNotFound was not prevented
255
+ // (handles either redirect changed or state lazy-definition)
256
+ to = redirect . to ;
257
+ toParams = redirect . toParams ;
258
+ options = redirect . options ;
259
+ toState = findState ( to , options . relative ) ;
260
+ if ( ! isDefined ( toState ) ) {
261
+ if ( options . relative ) throw new Error ( "Could not resolve '" + to + "' from state '" + options . relative + "'" ) ;
262
+ throw new Error ( "No such state '" + to + "'" ) ;
263
+ }
246
264
}
247
265
if ( toState [ 'abstract' ] ) throw new Error ( "Cannot transition to abstract state '" + to + "'" ) ;
248
266
if ( options . inherit ) toParams = inheritParams ( $stateParams , toParams || { } , $state . $current , toState ) ;
249
267
to = toState ;
250
268
251
- var toPath = to . path ,
252
- from = $state . $current , fromParams = $state . params , fromPath = from . path ;
269
+ var toPath = to . path ;
253
270
254
271
// Starting from the root of the path, keep all levels that haven't changed
255
272
var keep , state , locals = root . locals , toLocals = [ ] ;
@@ -272,7 +289,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory, $
272
289
toParams = normalize ( to . params , toParams || { } ) ;
273
290
274
291
// Broadcast start event and cancel the transition if requested
275
- var evt = $rootScope . $broadcast ( '$stateChangeStart' , to . self , toParams , from . self , fromParams ) ;
292
+ evt = $rootScope . $broadcast ( '$stateChangeStart' , to . self , toParams , from . self , fromParams ) ;
276
293
if ( evt . defaultPrevented ) return TransitionPrevented ;
277
294
278
295
// Resolve locals for the remaining states, but don't update any global state just
0 commit comments