Skip to content

Commit 0390359

Browse files
committed
feat(uiSref): add ui-sref-on attribute
Fixes angular-ui#1863, supersedes angular-ui#1877
1 parent dba25db commit 0390359

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

src/stateDirectives.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ function stateContext(el) {
4141
* using the `ui-sref-opts` attribute. Options are restricted to `location`, `inherit`,
4242
* and `reload`.
4343
*
44+
* You can invoke an expression when this state transition is initiated using
45+
* the `ui-sref-on` attribute. The promise returned by {@link
46+
* ui.router.state.$state#methods_go $state.go()} is injected into the expression as
47+
* `$template`.
48+
*
4449
* @example
4550
* Here's an example of how you'd use ui-sref and how it would compile. If you have the
4651
* following template:
@@ -75,6 +80,7 @@ function stateContext(el) {
7580
*
7681
* @param {string} ui-sref 'stateName' can be any valid absolute or relative state
7782
* @param {Object} ui-sref-opts options to pass to {@link ui.router.state.$state#go $state.go()}
83+
* @param {expression} ui-sref-on expression to evaluate when transition starts. Result of {@link ui.router.state.$state#methods_go $state.go()} is injected as '$transition'
7884
*/
7985
$StateRefDirective.$inject = ['$state', '$timeout'];
8086
function $StateRefDirective($state, $timeout) {
@@ -134,7 +140,13 @@ function $StateRefDirective($state, $timeout) {
134140
if ( !(button > 1 || e.ctrlKey || e.metaKey || e.shiftKey || element.attr('target')) ) {
135141
// HACK: This is to allow ng-clicks to be processed before the transition is initiated:
136142
var transition = $timeout(function() {
137-
$state.go(ref.state, params, options);
143+
var $transition = $state.go(ref.state, params, options);
144+
if ($transition && attrs.uiSrefOn) {
145+
if (angular.version.minor < 2) throw new Error("uiSrefOn not supported by angular < 1.2.0");
146+
scope.$eval(attrs.uiSrefOn, {
147+
$transition: $transition
148+
});
149+
}
138150
});
139151
e.preventDefault();
140152

test/stateDirectivesSpec.js

+36
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,42 @@ describe('uiStateRef', function() {
389389
expect(transitionOptions.notify).toBeUndefined();
390390
}));
391391
});
392+
393+
describe('transition expression', function() {
394+
beforeEach(inject(function($rootScope, $compile) {
395+
el = angular.element('<a ui-sref="contacts.item.detail({id: 5})" ui-sref-on="loading = $transition">Details</a>');
396+
scope = $rootScope;
397+
scope.loading = null;
398+
399+
$compile(el)(scope);
400+
scope.$digest();
401+
}));
402+
403+
it('applies an expression when a transition begins', inject(function($rootScope, $timeout, $state) {
404+
if (angular.version.minor < 2) return;
405+
406+
var newState;
407+
408+
expect(scope.loading).toBe(null);
409+
triggerClick(el);
410+
$timeout.flush();
411+
412+
expect(scope.loading.then).toEqual(jasmine.any(Function));
413+
414+
scope.loading.then(function(_newState) {
415+
newState = _newState;
416+
});
417+
418+
$rootScope.$digest();
419+
expect(newState).toEqual($state.get('contacts.item.detail'));
420+
}));
421+
422+
it('throws on < 1.2.0 due to $parse promise mangling', inject(function($timeout) {
423+
if (angular.version.minor >= 2) return;
424+
triggerClick(el);
425+
expect($timeout.flush).toThrow("uiSrefOn not supported by angular < 1.2.0");
426+
}));
427+
});
392428
});
393429

394430
describe('uiSrefActive', function() {

0 commit comments

Comments
 (0)