@@ -137,31 +137,34 @@ function $ViewDirective( $state, $compile, $controller, $injector, $ui
137
137
138
138
// Returns a set of DOM manipulation functions based on whether animation
139
139
// should be performed
140
- function getRenderer ( element , attrs , scope ) {
140
+ function getRenderer ( attrs , scope ) {
141
141
var statics = function ( ) {
142
142
return {
143
- leave : function ( element ) { element . remove ( ) ; } ,
144
- enter : function ( element , parent , anchor ) { anchor . after ( element ) ; }
143
+ enter : function ( element , target , cb ) {
144
+ target . after ( element ) ;
145
+ target . remove ( ) ;
146
+ if ( typeof cb === 'function' ) cb ( ) ;
147
+ } ,
148
+ leave : function ( element , cb ) {
149
+ element . remove ( ) ;
150
+ if ( typeof cb === 'function' ) cb ( ) ;
151
+ }
145
152
} ;
146
153
} ;
147
154
148
155
if ( $animate ) {
149
- return function ( shouldAnimate ) {
150
- return ! shouldAnimate ? statics ( ) : {
151
- enter : function ( element , parent , anchor ) { $animate . enter ( element , null , anchor ) ; } ,
152
- leave : function ( element ) { $animate . leave ( element , function ( ) { element . remove ( ) ; } ) ; }
153
- } ;
156
+ return {
157
+ enter : function ( element , target , cb ) { $animate . enter ( element , null , target , cb || angular . noop ) ; } ,
158
+ leave : function ( element , cb ) { $animate . leave ( element , cb || angular . noop ) ; }
154
159
} ;
155
160
}
156
161
157
162
if ( $animator ) {
158
163
var animate = $animator && $animator ( scope , attrs ) ;
159
164
160
- return function ( shouldAnimate ) {
161
- return ! shouldAnimate ? statics ( ) : {
162
- enter : function ( element , parent , anchor ) { animate . enter ( element , parent ) ; } ,
163
- leave : function ( element ) { animate . leave ( element . contents ( ) , element ) ; }
164
- } ;
165
+ return {
166
+ enter : function ( element , target , cb ) { animate . enter ( element , target , cb || angular . noop ) ; } ,
167
+ leave : function ( element , cb ) { animate . leave ( element . contents ( ) , element , cb || angular . noop ) ; }
165
168
} ;
166
169
}
167
170
@@ -170,118 +173,130 @@ function $ViewDirective( $state, $compile, $controller, $injector, $ui
170
173
171
174
var directive = {
172
175
restrict : 'ECA' ,
173
- compile : function ( element , attrs ) {
174
- var initial = element . html ( ) ,
175
- isDefault = true ,
176
- anchor = angular . element ( $document [ 0 ] . createComment ( ' ui-view-anchor ' ) ) ,
177
- parentEl = element . parent ( ) ;
178
-
179
- element . prepend ( anchor ) ;
180
-
181
- return function ( $scope ) {
182
- var inherited = parentEl . inheritedData ( '$uiView' ) ;
183
-
184
- var currentScope , currentEl , viewLocals ,
185
- name = attrs [ directive . name ] || attrs . name || '' ,
186
- onloadExp = attrs . onload || '' ,
187
- autoscrollExp = attrs . autoscroll ,
188
- renderer = getRenderer ( element , attrs , $scope ) ;
189
-
190
- if ( name . indexOf ( '@' ) < 0 ) name = name + '@' + ( inherited ? inherited . state . name : '' ) ;
191
- var view = { name : name , state : null } ;
192
-
193
- var eventHook = function ( ) {
194
- if ( viewIsUpdating ) return ;
195
- viewIsUpdating = true ;
196
-
197
- try { updateView ( true ) ; } catch ( e ) {
198
- viewIsUpdating = false ;
199
- throw e ;
200
- }
176
+ terminal : true ,
177
+ priority : 400 ,
178
+ transclude : 'element' ,
179
+ link : function ( scope , $element , attrs , ctrl , $transclude ) {
180
+ var currentScope , currentEl , previousEl , viewLocals ,
181
+ onloadExp = attrs . onload || '' ,
182
+ autoscrollExp = attrs . autoscroll ,
183
+ renderer = getRenderer ( attrs , scope ) ,
184
+ parentEl = $element . parent ( ) ,
185
+ inherited = parentEl . inheritedData ( '$uiView' ) ,
186
+ name = attrs [ directive . name ] || attrs . name || '' ;
187
+
188
+ if ( name . indexOf ( '@' ) < 0 ) name = name + '@' + ( inherited ? inherited . state . name : '' ) ;
189
+
190
+ var eventHook = function ( ) {
191
+ if ( viewIsUpdating ) return ;
192
+
193
+ viewIsUpdating = true ;
194
+
195
+ try { updateView ( ) ; } catch ( e ) {
196
+ throw e ;
197
+ } finally {
201
198
viewIsUpdating = false ;
202
- } ;
203
-
204
- $scope . $on ( '$stateChangeSuccess' , eventHook ) ;
205
- $scope . $on ( '$viewContentLoading' , eventHook ) ;
199
+ }
200
+ } ;
206
201
207
- updateView ( false ) ;
202
+ scope . $on ( '$stateChangeSuccess' , eventHook ) ;
203
+ scope . $on ( '$viewContentLoading' , eventHook ) ;
204
+ updateView ( ) ;
208
205
209
- function cleanupLastView ( ) {
210
- if ( currentEl ) {
211
- renderer ( true ) . leave ( currentEl ) ;
212
- currentEl = null ;
213
- }
206
+ function cleanupLastView ( ) {
207
+ if ( previousEl ) {
208
+ previousEl . remove ( ) ;
209
+ previousEl = null ;
210
+ }
214
211
215
- if ( currentScope ) {
216
- currentScope . $destroy ( ) ;
217
- currentScope = null ;
218
- }
212
+ if ( currentScope ) {
213
+ currentScope . $destroy ( ) ;
214
+ currentScope = null ;
219
215
}
220
216
221
- function updateView ( shouldAnimate ) {
222
- var locals = $state . $current && $state . $current . locals [ name ] ;
217
+ if ( currentEl ) {
218
+ renderer . leave ( currentEl , function ( ) {
219
+ previousEl = null ;
220
+ } ) ;
223
221
224
- if ( isDefault ) {
225
- isDefault = false ;
226
- element . replaceWith ( anchor ) ;
227
- }
222
+ previousEl = currentEl ;
223
+ currentEl = null ;
224
+ }
225
+ }
228
226
229
- if ( ! locals ) {
230
- cleanupLastView ( ) ;
231
- currentEl = element . clone ( ) ;
232
- currentEl . html ( initial ) ;
233
- renderer ( shouldAnimate ) . enter ( currentEl , parentEl , anchor ) ;
227
+ function updateView ( ) {
228
+ var newScope = scope . $new ( ) ,
229
+ locals = $state . $current && $state . $current . locals [ name ] ;
234
230
235
- currentScope = $scope . $new ( ) ;
236
- $compile ( currentEl . contents ( ) ) ( currentScope ) ;
237
- return ;
238
- }
231
+ if ( locals === viewLocals ) return ; // nothing to do
239
232
240
- if ( locals === viewLocals ) return ; // nothing to do
233
+ viewLocals = locals ;
241
234
235
+ var clone = $transclude ( newScope , function ( clone ) {
236
+ clone . data ( '$uiViewName' , name ) ;
237
+ renderer . enter ( clone , currentEl || $element , function onUiViewEnter ( ) {
238
+ if ( ! angular . isDefined ( autoscrollExp ) || ! autoscrollExp || scope . $eval ( autoscrollExp ) ) {
239
+ $uiViewScroll ( clone ) ;
240
+ }
241
+ } ) ;
242
242
cleanupLastView ( ) ;
243
+ } ) ;
244
+
245
+ currentEl = clone ;
246
+ currentScope = newScope ;
247
+
248
+ /**
249
+ * @ngdoc event
250
+ * @name ui.router.state.directive:ui-view#$viewContentLoaded
251
+ * @eventOf ui.router.state.directive:ui-view
252
+ * @eventType emits on ui-view directive scope
253
+ * @description *
254
+ * Fired once the view is **loaded**, *after* the DOM is rendered.
255
+ *
256
+ * @param {Object } event Event object.
257
+ */
258
+ currentScope . $emit ( '$viewContentLoaded' ) ;
259
+ if ( onloadExp ) currentScope . $eval ( onloadExp ) ;
260
+ }
261
+ }
262
+ } ;
243
263
244
- currentEl = element . clone ( ) ;
245
- currentEl . html ( locals . $template ? locals . $template : initial ) ;
246
- renderer ( true ) . enter ( currentEl , parentEl , anchor ) ;
264
+ return directive ;
265
+ }
247
266
248
- currentEl . data ( '$uiView' , view ) ;
267
+ $ViewDirectiveFill . $inject = [ '$compile' , '$controller' , '$state' ] ;
268
+ function $ViewDirectiveFill ( $compile , $controller , $state ) {
269
+ var directive = {
270
+ restrict : 'ECA' ,
271
+ priority : - 400 ,
272
+ compile : function ( tElement ) {
273
+ var initial = tElement . html ( ) ;
249
274
250
- viewLocals = locals ;
251
- view . state = locals . $$state ;
275
+ return function ( scope , $element ) {
276
+ var current = $state . $current ,
277
+ name = $element . data ( '$uiViewName' ) ,
278
+ locals = current && current . locals [ name ] ;
252
279
253
- var link = $compile ( currentEl . contents ( ) ) ;
280
+ if ( ! locals ) {
281
+ return ;
282
+ }
254
283
255
- currentScope = $scope . $new ( ) ;
284
+ $element . data ( '$uiView' , { name : name , state : locals . $$state } ) ;
285
+ $element . html ( locals . $template ? locals . $template : initial ) ;
256
286
257
- if ( locals . $$controller ) {
258
- locals . $scope = currentScope ;
259
- var controller = $controller ( locals . $$controller , locals ) ;
260
- if ( $state . $current . controllerAs ) {
261
- currentScope [ $state . $current . controllerAs ] = controller ;
262
- }
263
- currentEl . children ( ) . data ( '$ngControllerController' , controller ) ;
264
- }
287
+ var link = $compile ( $element . contents ( ) ) ;
265
288
266
- link ( currentScope ) ;
267
-
268
- /**
269
- * @ngdoc event
270
- * @name ui.router.state.directive:ui-view#$viewContentLoaded
271
- * @eventOf ui.router.state.directive:ui-view
272
- * @eventType emits on ui-view directive scope
273
- * @description *
274
- * Fired once the view is **loaded**, *after* the DOM is rendered.
275
- *
276
- * @param {Object } event Event object.
277
- */
278
- currentScope . $emit ( '$viewContentLoaded' ) ;
279
- if ( onloadExp ) currentScope . $eval ( onloadExp ) ;
280
-
281
- if ( ! angular . isDefined ( autoscrollExp ) || ! autoscrollExp || $scope . $eval ( autoscrollExp ) ) {
282
- $uiViewScroll ( currentEl ) ;
289
+ if ( locals . $$controller ) {
290
+ locals . $scope = scope ;
291
+ var controller = $controller ( locals . $$controller , locals ) ;
292
+ if ( current . controllerAs ) {
293
+ scope [ current . controllerAs ] = controller ;
283
294
}
295
+ $element . data ( '$ngControllerController' , controller ) ;
296
+ $element . children ( ) . data ( '$ngControllerController' , controller ) ;
284
297
}
298
+
299
+ link ( scope ) ;
285
300
} ;
286
301
}
287
302
} ;
@@ -290,3 +305,4 @@ function $ViewDirective( $state, $compile, $controller, $injector, $ui
290
305
}
291
306
292
307
angular . module ( 'ui.router.state' ) . directive ( 'uiView' , $ViewDirective ) ;
308
+ angular . module ( 'ui.router.state' ) . directive ( 'uiView' , $ViewDirectiveFill ) ;
0 commit comments