22
22
$StateProvider . $inject = [ '$urlRouterProvider' , '$urlMatcherFactoryProvider' ] ;
23
23
function $StateProvider ( $urlRouterProvider , $urlMatcherFactory ) {
24
24
25
- var root , states = { } , $state , queue = { } , abstractKey = 'abstract' ;
25
+ var root , states = { } , $state , queue = { } , abstractKey = 'abstract' , isRuntime = false ;
26
26
27
27
// Builds state properties from definition passed to registerState()
28
28
var stateBuilder = {
@@ -64,12 +64,19 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
64
64
return state . url ? state : ( state . parent ? state . parent . navigable : null ) ;
65
65
} ,
66
66
67
+ // Own parameters for this state. state.url.params is already built at this point. Create and add non-url params
68
+ ownParams : function ( state ) {
69
+ var params = state . url && state . url . params || new $$UMFP . ParamSet ( ) ;
70
+ forEach ( state . params || { } , function ( config , id ) {
71
+ if ( ! params [ id ] ) params [ id ] = new $$UMFP . Param ( id , null , config ) ;
72
+ } ) ;
73
+ return params ;
74
+ } ,
75
+
67
76
// Derive parameters for this state and ensure they're a super-set of parent's parameters
68
77
params : function ( state ) {
69
- if ( ! state . params ) {
70
- return state . url ? state . url . params : state . parent . params ;
71
- }
72
- return state . params ;
78
+ var parentParams = state . parent && state . parent . params || new $$UMFP . ParamSet ( ) ;
79
+ return inherit ( parentParams , state . ownParams ) ;
73
80
} ,
74
81
75
82
// If there is no explicit multi-view configuration, make one up so we don't have
@@ -87,28 +94,6 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
87
94
return views ;
88
95
} ,
89
96
90
- ownParams : function ( state ) {
91
- state . params = state . params || { } ;
92
-
93
- if ( ! state . parent ) {
94
- return objectKeys ( state . params ) ;
95
- }
96
- var paramNames = { } ; forEach ( state . params , function ( v , k ) { paramNames [ k ] = true ; } ) ;
97
-
98
- forEach ( state . parent . params , function ( v , k ) {
99
- if ( ! paramNames [ k ] ) {
100
- throw new Error ( "Missing required parameter '" + k + "' in state '" + state . name + "'" ) ;
101
- }
102
- paramNames [ k ] = false ;
103
- } ) ;
104
- var ownParams = [ ] ;
105
-
106
- forEach ( paramNames , function ( own , p ) {
107
- if ( own ) ownParams . push ( p ) ;
108
- } ) ;
109
- return ownParams ;
110
- } ,
111
-
112
97
// Keep a full path from the root down to this state as this is needed for state activation.
113
98
path : function ( state ) {
114
99
return state . parent ? state . parent . path . concat ( state ) : [ ] ; // exclude root from path
@@ -171,6 +156,13 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
171
156
queue [ parentName ] . push ( state ) ;
172
157
}
173
158
159
+ function flushQueuedChildren ( parentName ) {
160
+ var queued = queue [ parentName ] || [ ] ;
161
+ while ( queued . length ) {
162
+ registerState ( queued . shift ( ) ) ;
163
+ }
164
+ }
165
+
174
166
function registerState ( state ) {
175
167
// Wrap a new object around the state so we can store our private details easily.
176
168
state = inherit ( state , {
@@ -186,10 +178,11 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
186
178
// Get parent name
187
179
var parentName = ( name . indexOf ( '.' ) !== - 1 ) ? name . substring ( 0 , name . lastIndexOf ( '.' ) )
188
180
: ( isString ( state . parent ) ) ? state . parent
181
+ : ( isObject ( state . parent ) && isString ( state . parent . name ) ) ? state . parent . name
189
182
: '' ;
190
183
191
184
// If parent is not registered yet, add state to queue and register later
192
- if ( parentName && ! states [ parentName ] ) {
185
+ if ( name !== "" && ( ! isRuntime || ! states [ parentName ] ) ) {
193
186
return queueState ( parentName , state . self ) ;
194
187
}
195
188
@@ -208,11 +201,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
208
201
}
209
202
210
203
// Register any queued children
211
- if ( queue [ name ] ) {
212
- for ( var i = 0 ; i < queue [ name ] . length ; i ++ ) {
213
- registerState ( queue [ name ] [ i ] ) ;
214
- }
215
- }
204
+ flushQueuedChildren ( name ) ;
216
205
217
206
return state ;
218
207
}
@@ -538,8 +527,8 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
538
527
* you're coming from.
539
528
*/
540
529
this . $get = $get ;
541
- $get . $inject = [ '$rootScope' , '$q' , '$view' , '$injector' , '$resolve' , '$stateParams' , '$urlRouter' ] ;
542
- function $get ( $rootScope , $q , $view , $injector , $resolve , $stateParams , $urlRouter ) {
530
+ $get . $inject = [ '$rootScope' , '$q' , '$view' , '$injector' , '$resolve' , '$stateParams' , '$urlRouter' , '$location' , '$urlMatcherFactory' ] ;
531
+ function $get ( $rootScope , $q , $view , $injector , $resolve , $stateParams , $urlRouter , $location , $urlMatcherFactory ) {
543
532
544
533
var TransitionSuperseded = $q . reject ( new Error ( 'transition superseded' ) ) ;
545
534
var TransitionPrevented = $q . reject ( new Error ( 'transition prevented' ) ) ;
@@ -793,6 +782,9 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
793
782
}
794
783
if ( toState [ abstractKey ] ) throw new Error ( "Cannot transition to abstract state '" + to + "'" ) ;
795
784
if ( options . inherit ) toParams = inheritParams ( $stateParams , toParams || { } , $state . $current , toState ) ;
785
+ if ( ! toState . params . $$validates ( toParams ) ) return TransitionFailed ;
786
+
787
+ toParams = toState . params . $$values ( toParams ) ;
796
788
to = toState ;
797
789
798
790
var toPath = to . path ;
@@ -801,7 +793,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
801
793
var keep = 0 , state = toPath [ keep ] , locals = root . locals , toLocals = [ ] ;
802
794
803
795
if ( ! options . reload ) {
804
- while ( state && state === fromPath [ keep ] && equalForKeys ( toParams , fromParams , state . ownParams ) ) {
796
+ while ( state && state === fromPath [ keep ] && state . ownParams . $$equals ( toParams , fromParams ) ) {
805
797
locals = toLocals [ keep ] = state . locals ;
806
798
keep ++ ;
807
799
state = toPath [ keep ] ;
@@ -820,7 +812,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
820
812
}
821
813
822
814
// Filter parameters before we pass them to event handlers etc.
823
- toParams = filterByKeys ( objectKeys ( to . params ) , toParams || { } ) ;
815
+ toParams = filterByKeys ( to . params . $$keys ( ) , toParams || { } ) ;
824
816
825
817
// Broadcast start event and cancel the transition if requested
826
818
if ( options . notify ) {
@@ -1133,7 +1125,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
1133
1125
if ( ! nav || nav . url === undefined || nav . url === null ) {
1134
1126
return null ;
1135
1127
}
1136
- return $urlRouter . href ( nav . url , filterByKeys ( objectKeys ( state . params ) , params || { } ) , {
1128
+ return $urlRouter . href ( nav . url , filterByKeys ( state . params . $$keys ( ) , params || { } ) , {
1137
1129
absolute : options . absolute
1138
1130
} ) ;
1139
1131
} ;
@@ -1162,7 +1154,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
1162
1154
// necessary. In addition to being available to the controller and onEnter/onExit callbacks,
1163
1155
// we also need $stateParams to be available for any $injector calls we make during the
1164
1156
// dependency resolution process.
1165
- var $stateParams = ( paramsAreFiltered ) ? params : filterByKeys ( objectKeys ( state . params ) , params ) ;
1157
+ var $stateParams = ( paramsAreFiltered ) ? params : filterByKeys ( state . params . $$keys ( ) , params ) ;
1166
1158
var locals = { $stateParams : $stateParams } ;
1167
1159
1168
1160
// Resolve 'global' dependencies for the state, i.e. those not specific to a view.
@@ -1203,6 +1195,9 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {
1203
1195
} ) ;
1204
1196
}
1205
1197
1198
+ isRuntime = true ;
1199
+ flushQueuedChildren ( "" ) ;
1200
+
1206
1201
return $state ;
1207
1202
}
1208
1203
0 commit comments