diff --git a/modules/angular1_router/lib/facades.es5 b/modules/angular1_router/lib/facades.es5 index 2be12cde28..aa2153e313 100644 --- a/modules/angular1_router/lib/facades.es5 +++ b/modules/angular1_router/lib/facades.es5 @@ -316,3 +316,13 @@ Location.prototype.path = function () { Location.prototype.go = function (path, query) { return $location.url(path + query); }; +Location.prototype.prepareExternalUrl = function(url) { + if (url.length > 0 && !url.startsWith('/')) { + url = '/' + url; + } + if(!$location.$$html5) { + return '#' + url; + } else { + return '.' + url; + } +}; diff --git a/modules/angular1_router/src/ng_outlet.ts b/modules/angular1_router/src/ng_outlet.ts index 191bd61d0e..f348020287 100644 --- a/modules/angular1_router/src/ng_outlet.ts +++ b/modules/angular1_router/src/ng_outlet.ts @@ -207,13 +207,13 @@ function ngLinkDirective($rootRouter, $parse) { return; } - let instruction = null; + let navigationInstruction = null; let link = attrs.ngLink || ''; function getLink(params) { - instruction = router.generate(params); + navigationInstruction = router.generate(params); - scope.$watch(function() { return router.isRouteActive(instruction); }, + scope.$watch(function() { return router.isRouteActive(navigationInstruction); }, function(active) { if (active) { element.addClass('ng-link-active'); @@ -222,7 +222,8 @@ function ngLinkDirective($rootRouter, $parse) { } }); - return './' + angular.stringifyInstruction(instruction); + const navigationHref = navigationInstruction.toLinkUrl(); + return $rootRouter._location.prepareExternalUrl(navigationHref); } let routeParamsGetter = $parse(link); @@ -236,11 +237,11 @@ function ngLinkDirective($rootRouter, $parse) { } element.on('click', event => { - if (event.which !== 1 || !instruction) { + if (event.which !== 1 || !navigationInstruction) { return; } - $rootRouter.navigateByInstruction(instruction); + $rootRouter.navigateByInstruction(navigationInstruction); event.preventDefault(); }); } diff --git a/modules/angular1_router/test/ng_link_spec.js b/modules/angular1_router/test/ng_link_spec.js index 22c59e63ac..4556230c2b 100644 --- a/modules/angular1_router/test/ng_link_spec.js +++ b/modules/angular1_router/test/ng_link_spec.js @@ -2,183 +2,173 @@ describe('ngLink', function () { - var elt, - $compile, - $rootScope, - $rootRouter, - $compileProvider; - - beforeEach(function () { - module('ng'); - module('ngComponentRouter'); - module(function (_$compileProvider_) { - $compileProvider = _$compileProvider_; - }); - - inject(function (_$compile_, _$rootScope_, _$rootRouter_) { - $compile = _$compile_; - $rootScope = _$rootScope_; - $rootRouter = _$rootRouter_; - }); - - registerComponent('userCmp', '
hello {{userCmp.$routeParams.name}}
', function () {}); - registerComponent('oneCmp', '
{{oneCmp.number}}
', function () {this.number = 'one'}); - registerComponent('twoCmp', '
{{twoCmp.number}}
', function () {this.number = 'two'}); - }); - - it('should allow linking from the parent to the child', function () { - $rootRouter.config([ + setup(); + configureRouter([ { path: '/a', component: 'oneCmp' }, { path: '/b', component: 'twoCmp', name: 'Two' } ]); - compile('link | outer {
}'); - - $rootRouter.navigateByUrl('/a'); - $rootScope.$digest(); + var elt = compile('link | outer {
}'); + navigateTo('/a'); expect(elt.find('a').attr('href')).toBe('./b'); }); it('should allow linking from the child and the parent', function () { - $rootRouter.config([ + setup(); + configureRouter([ { path: '/a', component: 'oneCmp' }, { path: '/b', component: 'twoCmp', name: 'Two' } ]); - compile('outer {
}'); - - $rootRouter.navigateByUrl('/b'); - $rootScope.$digest(); + var elt = compile('outer {
}'); + navigateTo('/b'); expect(elt.find('a').attr('href')).toBe('./b'); }); it('should allow params in routerLink directive', function () { + setup(); registerComponent('twoLinkCmp', '
{{twoLinkCmp.number}}
', function () {this.number = 'two'}); - - $rootRouter.config([ + configureRouter([ { path: '/a', component: 'twoLinkCmp' }, { path: '/b/:param', component: 'twoCmp', name: 'Two' } ]); - compile('
'); - - $rootRouter.navigateByUrl('/a'); - $rootScope.$digest(); + var elt = compile('
'); + navigateTo('/a'); expect(elt.find('a').attr('href')).toBe('./b/lol'); }); it('should update the href of links with bound params', function () { - registerComponent('twoLinkCmp', '
{{twoLinkCmp.number}}
', function () {this.number = 'param'}); - $rootRouter.config([ + setup(); + registerComponent('twoLinkCmp', '
{{$ctrl.number}}
', function () {this.number = 43}); + configureRouter([ { path: '/a', component: 'twoLinkCmp' }, { path: '/b/:param', component: 'twoCmp', name: 'Two' } ]); - compile('
'); - $rootRouter.navigateByUrl('/a'); - $rootScope.$digest(); - - expect(elt.find('a').attr('href')).toBe('./b/param'); + var elt = compile('
'); + navigateTo('/a'); + expect(elt.find('a').text()).toBe('43'); + expect(elt.find('a').attr('href')).toBe('./b/43'); }); it('should navigate on left-mouse click when a link url matches a route', function () { - $rootRouter.config([ + setup(); + configureRouter([ { path: '/', component: 'oneCmp' }, { path: '/two', component: 'twoCmp', name: 'Two'} ]); - compile('link |
'); - $rootScope.$digest(); + var elt = compile('link |
'); expect(elt.text()).toBe('link | one'); - expect(elt.find('a').attr('href')).toBe('./two'); elt.find('a')[0].click(); - - $rootScope.$digest(); + inject(function($rootScope) { $rootScope.$digest(); }); expect(elt.text()).toBe('link | two'); }); - it('should not navigate on non-left mouse click when a link url matches a route', inject(function ($rootRouter) { - $rootRouter.config([ + it('should not navigate on non-left mouse click when a link url matches a route', function() { + setup(); + configureRouter([ { path: '/', component: 'oneCmp' }, { path: '/two', component: 'twoCmp', name: 'Two'} ]); - compile('link |
'); - $rootScope.$digest(); + var elt = compile('link |
'); expect(elt.text()).toBe('link | one'); elt.find('a').triggerHandler({ type: 'click', which: 3 }); - - $rootScope.$digest(); + inject(function($rootScope) { $rootScope.$digest(); }); expect(elt.text()).toBe('link | one'); - })); + }); // See https://github.com/angular/router/issues/206 it('should not navigate a link without an href', function () { - $rootRouter.config([ + setup(); + configureRouter([ { path: '/', component: 'oneCmp' }, { path: '/two', component: 'twoCmp', name: 'Two'} ]); expect(function () { - compile('link'); - $rootScope.$digest(); + var elt = compile('link'); expect(elt.text()).toBe('link'); elt.find('a')[0].click(); - $rootScope.$digest(); + inject(function($rootScope) { $rootScope.$digest(); }); }).not.toThrow(); }); - it('should add an ng-link-active class on the current link', inject(function ($rootRouter) { - $rootRouter.config([ + it('should add an ng-link-active class on the current link', function() { + setup(); + configureRouter([ { path: '/', component: 'oneCmp', name: 'One' } ]); - compile('one |
'); - $rootScope.$digest(); - - $rootRouter.navigateByUrl('/'); - $rootScope.$digest(); - + var elt = compile('one |
'); + navigateTo('/'); expect(elt.find('a').attr('class')).toBe('ng-link-active'); - })); + }); - function registerComponent(name, template, config) { - var controller = function () {}; + describe('html5Mode disabled', function () { + it('should prepend href with a hash', function () { + setup({ html5Mode: false }); + module(function($locationProvider) { + $locationProvider.html5Mode(false); + }); + configureRouter([ + { path: '/b', component: 'twoCmp', name: 'Two' } + ]); + var elt = compile('link'); + expect(elt.find('a').attr('href')).toBe('#/b'); + }); + }); - function factory() { - return { + + function registerComponent(name, template, controller) { + module(function($compileProvider) { + $compileProvider.component(name, { template: template, - controllerAs: name, controller: controller - }; - } + }); + }); + } - if (!template) { - template = ''; - } - if (angular.isArray(config)) { - factory.annotations = [new angular.annotations.RouteConfig(config)]; - } else if (typeof config === 'function') { - controller = config; - } else if (typeof config === 'object') { - if (config.canActivate) { - controller.$canActivate = config.canActivate; - } - } - $compileProvider.directive(name, factory); + function setup(config) { + var html5Mode = !(config && config.html5Mode === false); + module('ngComponentRouter') + module(function($locationProvider) { + $locationProvider.html5Mode(html5Mode); + }); + registerComponent('userCmp', '
hello {{$ctrl.$routeParams.name}}
', function () {}); + registerComponent('oneCmp', '
{{$ctrl.number}}
', function () {this.number = 'one'}); + registerComponent('twoCmp', '
{{$ctrl.number}}
', function () {this.number = 'two'}); + } + + function configureRouter(routeConfig) { + inject(function($rootRouter) { + $rootRouter.config(routeConfig); + }); } function compile(template) { - elt = $compile('
' + template + '
')($rootScope); - $rootScope.$digest(); + var elt; + inject(function($compile, $rootScope) { + elt = $compile('
' + template + '
')($rootScope); + $rootScope.$digest(); + }); return elt; } + + function navigateTo(url) { + inject(function($rootRouter, $rootScope) { + $rootRouter.navigateByUrl(url); + $rootScope.$digest(); + }); + } });