Skip to content

Commit

Permalink
Merge pull request #1363 from angular-ui/issue-1362
Browse files Browse the repository at this point in the history
fix(uiSref): nagivate to state when url is ""
  • Loading branch information
christopherthielen committed Sep 12, 2014
2 parents 0569016 + 656b5aa commit 3fed931
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,7 @@ function $StateProvider( $urlRouterProvider, $urlMatcherFactory) {

var nav = (state && options.lossy) ? state.navigable : state;

if (!nav || !nav.url) {
if (!nav || nav.url === undefined || nav.url === null) {
return null;
}
return $urlRouter.href(nav.url, filterByKeys(objectKeys(state.params), params || {}), {
Expand Down
8 changes: 6 additions & 2 deletions src/stateDirectives.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ function $StateRefDirective($state, $timeout) {
link: function(scope, element, attrs, uiSrefActive) {
var ref = parseStateRef(attrs.uiSref, $state.current.name);
var params = null, url = null, base = stateContext(element) || $state.$current;
var newHref = null, isAnchor = element.prop("tagName") === "A";
var isForm = element[0].nodeName === "FORM";
var attr = isForm ? "action" : "href", nav = true;

Expand All @@ -102,7 +103,7 @@ function $StateRefDirective($state, $timeout) {
if (newVal) params = newVal;
if (!nav) return;

var newHref = $state.href(ref.state, params, options);
newHref = $state.href(ref.state, params, options);

var activeDirective = uiSrefActive[1] || uiSrefActive[0];
if (activeDirective) {
Expand Down Expand Up @@ -134,8 +135,11 @@ function $StateRefDirective($state, $timeout) {
});
e.preventDefault();

// if the state has no URL, ignore one preventDefault from the <a> directive.
var ignorePreventDefaultCount = isAnchor && !newHref ? 1: 0;
e.preventDefault = function() {
$timeout.cancel(transition);
if (ignorePreventDefaultCount-- <= 0)
$timeout.cancel(transition);
};
}
});
Expand Down
78 changes: 56 additions & 22 deletions test/stateDirectivesSpec.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
describe('uiStateRef', function() {

var el, template, scope, document;
var timeoutFlush, el, el2, template, scope, document, _locationProvider;

beforeEach(module('ui.router'));

beforeEach(module(function($stateProvider) {
beforeEach(module(function($stateProvider, $locationProvider) {
_locationProvider = $locationProvider;
$stateProvider.state('top', {
url: ''
}).state('contacts', {
Expand Down Expand Up @@ -74,29 +75,30 @@ describe('uiStateRef', function() {
}));
});

describe('links', function() {
var timeoutFlush, el2;

beforeEach(inject(function($rootScope, $compile, $timeout) {
el = angular.element('<a ui-sref="contacts.item.detail({ id: contact.id })">Details</a>');
el2 = angular.element('<a ui-sref="top">Top</a>');
scope = $rootScope;
scope.contact = { id: 5 };
scope.$apply();
function buildDOM($rootScope, $compile, $timeout) {
el = angular.element('<a ui-sref="contacts.item.detail({ id: contact.id })">Details</a>');
el2 = angular.element('<a ui-sref="top">Top</a>');
scope = $rootScope;
scope.contact = { id: 5 };
scope.$apply();

$compile(el)(scope);
$compile(el2)(scope);
scope.$digest();
$compile(el)(scope);
$compile(el2)(scope);
scope.$digest();

timeoutFlush = function() {
try {
$timeout.flush();
} catch (e) {
// Angular 1.0.8 throws 'No deferred tasks to be flushed' if there is nothing in queue.
// Behave as Angular >=1.1.5 and do nothing in such case.
}
timeoutFlush = function () {
try {
$timeout.flush();
} catch (e) {
// Angular 1.0.8 throws 'No deferred tasks to be flushed' if there is nothing in queue.
// Behave as Angular >=1.1.5 and do nothing in such case.
}
}));
}
};

describe('links', function() {
beforeEach(inject(buildDOM));

it('should generate the correct href', function() {
expect(el.attr('href')).toBe('#/contacts/5');
Expand Down Expand Up @@ -217,7 +219,7 @@ describe('uiStateRef', function() {
expect($state.current.name).toEqual('top');
expect($stateParams).toEqualData({});
}));

it('should allow passing params to current state', inject(function($compile, $rootScope, $state) {
$state.current.name = 'contacts.item.detail';

Expand All @@ -243,6 +245,38 @@ describe('uiStateRef', function() {
}));
});

describe('links in html5 mode', function() {
beforeEach(function() {
_locationProvider.html5Mode(true);
});

beforeEach(inject(buildDOM));

it('should generate the correct href', function() {
expect(el.attr('href')).toBe('/contacts/5');
expect(el2.attr('href')).toBe('');
});

it('should update the href when parameters change', function() {
expect(el.attr('href')).toBe('/contacts/5');
scope.contact.id = 6;
scope.$apply();
expect(el.attr('href')).toBe('/contacts/6');
});

it('should transition states when the url is empty', inject(function($state, $stateParams, $q) {
// Odd, in html5Mode, the initial state isn't matching on empty url, but does match if top.url is "/".
// expect($state.$current.name).toEqual('top');

triggerClick(el2);
timeoutFlush();
$q.flush();

expect($state.current.name).toEqual('top');
expect($stateParams).toEqualData({});
}));
});

describe('forms', function() {
var el, scope;

Expand Down

0 comments on commit 3fed931

Please sign in to comment.