Skip to content

Commit 4602609

Browse files
committed
fix(uiSref): various click-related issues
- Always invoke digest loop - Use $timeout to defer transition until other click events have processed
1 parent 1f56360 commit 4602609

File tree

2 files changed

+16
-7
lines changed

2 files changed

+16
-7
lines changed

src/stateDirectives.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ function stateContext(el) {
1212
}
1313
}
1414

15-
$StateRefDirective.$inject = ['$state'];
16-
function $StateRefDirective($state) {
15+
$StateRefDirective.$inject = ['$state', '$timeout'];
16+
function $StateRefDirective($state, $timeout) {
1717
return {
1818
restrict: 'A',
1919
require: '?^uiSrefActive',
@@ -53,8 +53,11 @@ function $StateRefDirective($state) {
5353
var button = e.which || e.button;
5454

5555
if ((button === 0 || button == 1) && !e.ctrlKey && !e.metaKey && !e.shiftKey) {
56-
scope.$evalAsync(function() {
57-
$state.go(ref.state, params, { relative: base });
56+
// HACK: This is to allow ng-clicks to be processed before the transition is initiated:
57+
$timeout(function() {
58+
scope.$apply(function() {
59+
$state.go(ref.state, params, { relative: base });
60+
});
5861
});
5962
e.preventDefault();
6063
}

test/stateDirectivesSpec.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,11 @@ describe('uiStateRef', function() {
100100
expect(el.attr('href')).toBe('#/contacts/3');
101101
}));
102102

103-
it('should transition states when left-clicked', inject(function($state, $stateParams, $document, $q) {
103+
it('should transition states when left-clicked', inject(function($state, $stateParams, $document, $q, $timeout) {
104104
expect($state.$current.name).toEqual('');
105105

106106
triggerClick(el);
107+
$timeout.flush();
107108
$q.flush();
108109

109110
expect($state.current.name).toEqual('contacts.item.detail');
@@ -181,37 +182,42 @@ describe('uiStateRef', function() {
181182
scope.$digest();
182183
}));
183184

184-
it('should work', inject(function ($state, $stateParams, $q) {
185+
it('should work', inject(function ($state, $stateParams, $q, $timeout) {
185186
triggerClick(el);
187+
$timeout.flush();
186188
$q.flush();
187189

188190
expect($state.$current.name).toBe("contacts.item.detail");
189191
expect($state.params).toEqual({ id: '5' });
190192
}));
191193

192-
it('should resolve states from parent uiView', inject(function ($state, $stateParams, $q) {
194+
it('should resolve states from parent uiView', inject(function ($state, $stateParams, $q, $timeout) {
193195
$state.transitionTo('contacts');
194196
$q.flush();
195197

196198
var parentToChild = angular.element(template[0].querySelector('a.item'));
197199
triggerClick(parentToChild);
200+
$timeout.flush();
198201
$q.flush();
199202

200203
var childToGrandchild = angular.element(template[0].querySelector('a.item-detail'));
201204
var childToParent = angular.element(template[0].querySelector('a.item-parent'));
202205

203206
triggerClick(childToGrandchild);
207+
$timeout.flush();
204208
$q.flush();
205209

206210
var grandchildToParent = angular.element(template[0].querySelector('a.item-parent2'));
207211
expect($state.$current.name).toBe("contacts.item.detail")
208212

209213
triggerClick(grandchildToParent);
214+
$timeout.flush();
210215
$q.flush();
211216
expect($state.$current.name).toBe("contacts.item");
212217

213218
$state.transitionTo("contacts.item.detail", { id: 3 });
214219
triggerClick(childToParent);
220+
$timeout.flush();
215221
$q.flush();
216222
expect($state.$current.name).toBe("contacts");
217223
}));

0 commit comments

Comments
 (0)