Skip to content

Commit a94117d

Browse files
fix(uiView): separate $uiView and $uiViewAnim element.data()
The `$uiView` element.data lifecycle is somewhat fragile. The Fill directive reads the inherited `$uiView` data to figure out which state the ui-view was created in. In a previous commit, the non-fill directive was setting the `$uiView` date earlier to hold the animation promises. This caused the fill directive to read the wrong state data, breaking some users' apps. BC-BREAK Users who were using `element.data('$uiView').$animEnter` or `$animLeave` should now use `element.data('$uiViewAnim').$animEnter` instead Closes #2763 Manually merged/cherry picked from commit d3502f3
1 parent 5638a65 commit a94117d

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

src/ng1/directives/viewDirective.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ import ITimeoutService = angular.ITimeoutService;
3131
export type UIViewData = {
3232
$cfg: Ng1ViewConfig;
3333
$uiView: ActiveUIView;
34+
}
3435

36+
/** @hidden */
37+
export type UIViewAnimData = {
3538
$animEnter: Promise<any>;
3639
$animLeave: Promise<any>;
3740
$$animLeave: { resolve: () => any; } // "deferred"
@@ -262,7 +265,7 @@ function $ViewDirective($view: ViewService, $animate: any, $uiViewScroll: any, $
262265
}
263266

264267
if (currentEl) {
265-
let _viewData = currentEl.data('$uiView');
268+
let _viewData = currentEl.data('$uiViewAnim');
266269
trace.traceUIViewEvent("Animate out", _viewData);
267270
renderer.leave(currentEl, function() {
268271
_viewData.$$animLeave.resolve();
@@ -281,13 +284,18 @@ function $ViewDirective($view: ViewService, $animate: any, $uiViewScroll: any, $
281284
let $uiViewData: UIViewData = {
282285
$cfg: config,
283286
$uiView: activeUIView,
287+
};
288+
289+
let $uiViewAnim: UIViewAnimData = {
284290
$animEnter: animEnter.promise,
285291
$animLeave: animLeave.promise,
286292
$$animLeave: animLeave
287293
};
288294

289295
let cloned = $transclude(newScope, function(clone) {
290-
renderer.enter(clone.data('$uiView', $uiViewData), $element, function onUIViewEnter() {
296+
clone.data('$uiViewAnim', $uiViewAnim);
297+
clone.data('$uiView', $uiViewData);
298+
renderer.enter(clone, $element, function onUIViewEnter() {
291299
animEnter.resolve();
292300
if (currentScope) currentScope.$emit('$viewContentAnimationEnded');
293301

test/ng1/viewDirectiveSpec.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ describe('uiView', function () {
113113
nState = {
114114
template: 'nState',
115115
controller: function ($scope, $element) {
116-
var data = $element.data('$uiView');
116+
var data = $element.data('$uiViewAnim');
117117
$scope.$on("$destroy", function() { log += 'destroy;'});
118118
data.$animEnter.then(function() { log += "animEnter;"});
119119
data.$animLeave.then(function() { log += "animLeave;"});
@@ -708,6 +708,24 @@ describe('uiView', function () {
708708
});
709709
});
710710

711+
describe("UiView", function() {
712+
beforeEach(module('ui.router'));
713+
beforeEach(module(function($stateProvider) {
714+
$stateProvider
715+
.state('main', { abstract: true, views: { main: {} } })
716+
.state('main.home', { views: { content: { template: 'home.html' } } });
717+
}));
718+
719+
it("shouldn't puke on weird view setups", inject(function($compile, $rootScope, $q, $state) {
720+
$compile('<div ui-view="main"><div ui-view="content"></div></div>')($rootScope);
721+
722+
$state.go('main.home');
723+
$q.flush();
724+
725+
expect($state.current.name).toBe('main.home');
726+
}));
727+
});
728+
711729
describe('uiView controllers or onEnter handlers', function() {
712730
var el, template, scope, document, count;
713731

0 commit comments

Comments
 (0)