Skip to content

Commit 2523bbd

Browse files
feat(ui-view): Add noanimation attribute to specify static renderer. fix(ui-view) use static renderer if animations not enabled . Closes #2485
1 parent 87f10df commit 2523bbd

File tree

2 files changed

+80
-33
lines changed

2 files changed

+80
-33
lines changed

src/viewDirective.js

+25-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
var ngMajorVer = angular.version.major;
2+
var ngMinorVer = angular.version.minor;
13
/**
24
* @ngdoc directive
35
* @name ui.router.state.directive:ui-view
@@ -22,6 +24,9 @@
2224
* service, {@link ui.router.state.$uiViewScroll}. This custom service let's you
2325
* scroll ui-view elements into view when they are populated during a state activation.
2426
*
27+
* @param {string=} noanimation If truthy, the non-animated renderer will be selected (no animations
28+
* will be applied to the ui-view)
29+
*
2530
* *Note: To revert back to old [`$anchorScroll`](http://docs.angularjs.org/api/ng.$anchorScroll)
2631
* functionality, call `$uiViewScrollProvider.useAnchorScroll()`.*
2732
*
@@ -133,24 +138,35 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
133138
// Returns a set of DOM manipulation functions based on which Angular version
134139
// it should use
135140
function getRenderer(attrs, scope) {
136-
var statics = function() {
137-
return {
138-
enter: function (element, target, cb) { target.after(element); cb(); },
139-
leave: function (element, cb) { element.remove(); cb(); }
140-
};
141+
var statics = {
142+
enter: function (element, target, cb) { target.after(element); cb(); },
143+
leave: function (element, cb) { element.remove(); cb(); }
141144
};
142145

146+
if (!!attrs.noanimation) return statics;
147+
148+
function animEnabled(element) {
149+
if (ngMajorVer === 1 && ngMinorVer >= 4) return !!$animate.enabled(element);
150+
if (ngMajorVer === 1 && ngMinorVer >= 2) return !!$animate.enabled();
151+
return (!!$animator);
152+
}
153+
154+
// ng 1.2+
143155
if ($animate) {
144156
return {
145157
enter: function(element, target, cb) {
146-
if (angular.version.minor > 2) {
158+
if (!animEnabled(element)) {
159+
statics.enter(element, target, cb);
160+
} else if (angular.version.minor > 2) {
147161
$animate.enter(element, null, target).then(cb);
148162
} else {
149163
$animate.enter(element, null, target, cb);
150164
}
151165
},
152166
leave: function(element, cb) {
153-
if (angular.version.minor > 2) {
167+
if (!animEnabled(element)) {
168+
statics.leave(element, cb);
169+
} else if (angular.version.minor > 2) {
154170
$animate.leave(element).then(cb);
155171
} else {
156172
$animate.leave(element, cb);
@@ -159,6 +175,7 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
159175
};
160176
}
161177

178+
// ng 1.1.5
162179
if ($animator) {
163180
var animate = $animator && $animator(scope, attrs);
164181

@@ -168,7 +185,7 @@ function $ViewDirective( $state, $injector, $uiViewScroll, $interpolate)
168185
};
169186
}
170187

171-
return statics();
188+
return statics;
172189
}
173190

174191
var directive = {

test/viewDirectiveSpec.js

+55-25
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,12 @@ describe('uiView', function () {
123123
.state('l', lState)
124124
.state('m', {
125125
controller: function($scope) {
126-
log += 'm;';
127-
$scope.$on('$destroy', function() {
128-
log += '$destroy(m);';
129-
});
130-
},
126+
log += 'ctrl(m);';
127+
$scope.$on('$destroy', function() { log += '$destroy(m);'; });
128+
}
131129
})
132130
.state('n', {
133-
controller: function($scope) {
134-
log += 'n;';
135-
},
131+
controller: function($scope) { log += 'ctrl(n);'; }
136132
});
137133
}));
138134

@@ -144,23 +140,6 @@ describe('uiView', function () {
144140

145141
describe('linking ui-directive', function () {
146142

147-
it('$destroy event is triggered after animation ends', inject(function($state, $q, $animate) {
148-
elem.append($compile('<div><ui-view></ui-view></div>')(scope));
149-
150-
$state.transitionTo('m');
151-
$q.flush();
152-
expect(log).toBe('m;');
153-
$state.transitionTo('n');
154-
$q.flush();
155-
if ($animate) {
156-
expect(log).toBe('m;n;');
157-
animateFlush($animate);
158-
expect(log).toBe('m;n;$destroy(m);');
159-
} else {
160-
expect(log).toBe('m;$destroy(m);n;');
161-
}
162-
}));
163-
164143
it('anonymous ui-view should be replaced with the template of the current $state', inject(function ($state, $q) {
165144
elem.append($compile('<div><ui-view></ui-view></div>')(scope));
166145

@@ -594,5 +573,56 @@ describe('uiView', function () {
594573
// No more animations
595574
expect($animate.queue.length).toBe(0);
596575
}));
576+
577+
it ('should disable animations if noanimation="true" is present', inject(function($state, $q, $compile, $animate) {
578+
var content = 'Initial Content', animation;
579+
elem.append($compile('<div><ui-view noanimation="true">' + content + '</ui-view></div>')(scope));
580+
581+
animation = $animate.queue.shift();
582+
expect(animation).toBeUndefined();
583+
584+
$state.transitionTo(aState);
585+
$q.flush();
586+
animation = $animate.queue.shift();
587+
expect(animation).toBeUndefined();
588+
expect(elem.text()).toBe(aState.template);
589+
590+
$state.transitionTo(bState);
591+
$q.flush();
592+
animation = $animate.queue.shift();
593+
expect(animation).toBeUndefined();
594+
expect(elem.text()).toBe(bState.template);
595+
}));
596+
597+
it('$destroy event is triggered after animation ends', inject(function($state, $q, $animate, $rootScope) {
598+
elem.append($compile('<div><ui-view></ui-view></div>')(scope));
599+
$rootScope.$on('$stateChangeSuccess', function(evt, toState) { log += 'success(' + toState.name + ');'; });
600+
601+
$state.transitionTo('m');
602+
$q.flush();
603+
expect(log).toBe('success(m);ctrl(m);');
604+
$state.transitionTo('n');
605+
$q.flush();
606+
if ($animate) {
607+
expect(log).toBe('success(m);ctrl(m);success(n);ctrl(n);');
608+
animateFlush($animate);
609+
expect(log).toBe('success(m);ctrl(m);success(n);ctrl(n);$destroy(m);');
610+
} else {
611+
expect(log).toBe('success(m);ctrl(m);$destroy(m);success(n);ctrl(n);');
612+
}
613+
}));
614+
615+
it('$destroy event is triggered before $stateChangeSuccess if noanimation is present', inject(function($state, $q, $animate, $rootScope) {
616+
elem.append($compile('<div><ui-view noanimation="true"></ui-view></div>')(scope));
617+
$rootScope.$on('$stateChangeSuccess', function(evt, toState) { log += 'success(' + toState.name + ');'; });
618+
619+
$state.transitionTo('m');
620+
$q.flush();
621+
expect(log).toBe('success(m);ctrl(m);');
622+
$state.transitionTo('n');
623+
$q.flush();
624+
expect(log).toBe('success(m);ctrl(m);success(n);$destroy(m);ctrl(n);');
625+
}));
626+
597627
});
598628
});

0 commit comments

Comments
 (0)