Angular 2 router no base href set
Asked Answered
S

8

230

I am getting an error and can't find why. Here is the error:

EXCEPTION: Error during instantiation of LocationStrategy! (RouterOutlet -> Router -> Location -> LocationStrategy).
    angular2.dev.js:23514 EXCEPTION: Error during instantiation of LocationStrategy! (RouterOutlet -> Router -> Location -> LocationStrategy).BrowserDomAdapter.logError @ angular2.dev.js:23514BrowserDomAdapter.logGroup @ angular2.dev.js:23525ExceptionHandler.call @ angular2.dev.js:1145(anonymous function) @ angular2.dev.js:14801NgZone._notifyOnError @ angular2.dev.js:5796collection_1.StringMapWrapper.merge.onError @ angular2.dev.js:5700run @ angular2-polyfills.js:141(anonymous function) @ angular2.dev.js:5719zoneBoundFn @ angular2-polyfills.js:111lib$es6$promise$$internal$$tryCatch @ angular2-polyfills.js:1511lib$es6$promise$$internal$$invokeCallback @ angular2-polyfills.js:1523lib$es6$promise$$internal$$publish @ angular2-polyfills.js:1494(anonymous function) @ angular2-polyfills.js:243microtask @ angular2.dev.js:5751run @ angular2-polyfills.js:138(anonymous function) @ angular2.dev.js:5719zoneBoundFn @ angular2-polyfills.js:111lib$es6$promise$asap$$flush @ angular2-polyfills.js:1305
    angular2.dev.js:23514 ORIGINAL EXCEPTION: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.BrowserDomAdapter.logError @ angular2.dev.js:23514ExceptionHandler.call @ angular2.dev.js:1154(anonymous function) @ angular2.dev.js:14801NgZone._notifyOnError @ angular2.dev.js:5796collection_1.StringMapWrapper.merge.onError @ angular2.dev.js:5700run @ angular2-polyfills.js:141(anonymous function) @ angular2.dev.js:5719zoneBoundFn @ angular2-polyfills.js:111lib$es6$promise$$internal$$tryCatch @ angular2-polyfills.js:1511lib$es6$promise$$internal$$invokeCallback @ angular2-polyfills.js:1523lib$es6$promise$$internal$$publish @ angular2-polyfills.js:1494(anonymous function) @ angular2-polyfills.js:243microtask @ angular2.dev.js:5751run @ angular2-polyfills.js:138(anonymous function) @ angular2.dev.js:5719zoneBoundFn @ angular2-polyfills.js:111lib$es6$promise$asap$$flush @ angular2-polyfills.js:1305
    angular2.dev.js:23514 ORIGINAL STACKTRACE:BrowserDomAdapter.logError @ angular2.dev.js:23514ExceptionHandler.call @ angular2.dev.js:1157(anonymous function) @ angular2.dev.js:14801NgZone._notifyOnError @ angular2.dev.js:5796collection_1.StringMapWrapper.merge.onError @ angular2.dev.js:5700run @ angular2-polyfills.js:141(anonymous function) @ angular2.dev.js:5719zoneBoundFn @ angular2-polyfills.js:111lib$es6$promise$$internal$$tryCatch @ angular2-polyfills.js:1511lib$es6$promise$$internal$$invokeCallback @ angular2-polyfills.js:1523lib$es6$promise$$internal$$publish @ angular2-polyfills.js:1494(anonymous function) @ angular2-polyfills.js:243microtask @ angular2.dev.js:5751run @ angular2-polyfills.js:138(anonymous function) @ angular2.dev.js:5719zoneBoundFn @ angular2-polyfills.js:111lib$es6$promise$asap$$flush @ angular2-polyfills.js:1305
    angular2.dev.js:23514 Error: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.
        at new BaseException (angular2.dev.js:8080)
        at new PathLocationStrategy (router.dev.js:1203)
        at angular2.dev.js:1380
        at Injector._instantiate (angular2.dev.js:11923)
        at Injector._instantiateProvider (angular2.dev.js:11859)
        at Injector._new (angular2.dev.js:11849)
        at InjectorDynamicStrategy.getObjByKeyId (angular2.dev.js:11733)
        at Injector._getByKeyDefault (angular2.dev.js:12048)
        at Injector._getByKey (angular2.dev.js:12002)
        at Injector._getByDependency (angular2.dev.js:11990)

Does anyone know why the router is throwing this? I am using angular2 beta

here is my code:

import {Component} from 'angular2/core';
import { RouteConfig, ROUTER_DIRECTIVES } from 'angular2/router';
import {LoginComponent} from './pages/login/login.component';
import {DashboardComponent} from './pages/dashboard/dashboard.component';
@Component({
    selector: 'app',
    directives:[ROUTER_DIRECTIVES],
    template:`
        <div class="wrapper">
            <router-outlet></router-outlet>
        </div>`
})
@RouteConfig([
    { path: '/',redirectTo: '/dashboard' },
    { path: '/login',name:'login',component: LoginComponent },
    { path: '/dashboard',name:'dashboard',component: DashboardComponent,}
])
export class AppComponent {
}
Stake answered 30/12, 2015 at 18:34 Comment(0)
B
413

https://angular.io/docs/ts/latest/guide/router.html

Add the base element just after the <head> tag. If the app folder is the application root, as it is for our application, set the href value exactly as shown here.

The <base href="/"> tells the Angular router what is the static part of the URL. The router then only modifies the remaining part of the URL.

<head>
  <base href="/">
  ...
</head>

Alternatively add

>= Angular2 RC.6

import {APP_BASE_HREF} from '@angular/common';

@NgModule({
  declarations: [AppComponent],
  imports: [routing /* or RouterModule */], 
  providers: [{provide: APP_BASE_HREF, useValue : '/' }]
]); 

in your bootstrap.

In older versions the imports had to be like

< Angular2 RC.6

import {APP_BASE_HREF} from '@angular/common';
bootstrap(AppComponent, [
  ROUTER_PROVIDERS, 
  {provide: APP_BASE_HREF, useValue : '/' });
]); 

< RC.0

import {provide} from 'angular2/core';
bootstrap(AppComponent, [
  ROUTER_PROVIDERS, 
  provide(APP_BASE_HREF, {useValue : '/' });
]); 

< beta.17

import {APP_BASE_HREF} from 'angular2/router';

>= beta.17

import {APP_BASE_HREF} from 'angular2/platform/common';

See also Location and HashLocationStrategy stopped working in beta.16

Beaumarchais answered 30/12, 2015 at 18:40 Comment(23)
Little example of second way: bootstrap(AppComponent, [ROUTER_PROVIDERS, provide(APP_BASE_HREF, {useValue : '/'})]);Maryettamaryjane
I had to add the import line import {provide} from 'angular2/core'; to be able to use provide.Sterling
I had to import line import {APP_BASE_HREF} from 'angular2/router';Preuss
Thanks for the updates. I don't use TS myself (only Dart) and my TS knowledge is still limited.Hujsak
I strongly recommend to include project directory structure here to make it more clear. I made an error by just include <base href="/"> in my project, because of the different project directory structure. It took me some time to figure out the reason.Cacography
What's you Project structure. / is common, for specific cases this might need a different path.Hujsak
as of this day, (january 14th 2017), <base href="/"> works fine for me, except when trying to test my app using TestBed. In this case, I have to provide a APP_BASE_HREFSarinasarine
@JCorriveau yes, it's supposed to work. Only when you serve the application on a subdirectory like http://example.org/somesub/index.html or similar, then you need a different path like base="/somesub"Hujsak
My project has SVG elements filled with image patterns. The images were never displayed in Firefox when <base href="/" /> was set in the file (for "/", "./", "#" or any other base path, no matter how the image paths themselves were specified in the pattern). The only solution that finally worked was to use APP_BASE_HREF instead. A real life saver!Pittman
hold on, but <base href="/"> is exactly the reason why angular builds are unable to be opened just by opening index.html from local folder (without web server)... I don't understand why angular need this base hrefSamhita
I doubt this is related. Angular needs a server because of security constraints in the browser (can be disabled by command line arguments). Angular can instead of <base> also be configured with APP_BASE_HREFHujsak
I want to add to your answer, if you have in your source index.html a <base> tag, it will override any APP_BASE_HREF or ng build --base-href; values. After removng it, I can modify the base href from any means.Omaromara
@DamjanDimitrioski I had expected the opposite. Inside Angular code APP_BASE_HREF should override <base href="...">. APP_BASE_HREF doesn't affect other areas where <base href="..."> has an effect, like SVG refs or similar.Hujsak
So, what's causing ng build to ignore the APP_BASE_HREF if base href is set in src index.html, in Angular 5.x ?Omaromara
@DamjanDimitrioski not sure what you mean with "ignore the APP_BASE_HREF". APP_BASE_HREF is only used by Angular code like the router or some custom code that might inject APP_BASE_HREF. Perhaps you expect it to have some effect it is not supposed to have?Hujsak
@GünterZöchbauer I expected setting --base-href /mypath to update the <base href="/mypath", but it didn't, removing the <base> from index.html(source) created the tag in the dist directory. This behaviour was not explained in any docs I read.Omaromara
I don't know about --base-href ..., but that doesn't seem to be related to APP_BASE_HREF, only to <base href="...">Hujsak
This is the right answer. I get this every time I create a new *.spec.ts test file. It is always required to build up a complete running environment.Celibacy
I had this error on a test .spec.ts while using Location. I add the RouterTestingModule and the error goes awayAdvertising
Using {provide: APP_BASE_HREF, useValue : '/' } worked for meSymploce
Not working. Angular modules start throwing NullInjector errorsRecto
does this mean you have to hardcode the base in the index file if you're not using the HashLocationStrategy? this would be a problem when deploying in a context which is not root, isn't there a better solution without having to change the index file?Invigilate
@Invigilate You can use string replacement in a build step, or use some JavaScript to change the value before Angular is started for example deriving it from the current location. There are probably other ways I'm not thinking of currently.Hujsak
E
38

I had faced similar issue with Angular4 and Jasmine unit tests; below given solution worked for me

Add below import statement

import { APP_BASE_HREF } from '@angular/common';

Add below statement for TestBed configuration:

TestBed.configureTestingModule({
    providers: [
        { provide: APP_BASE_HREF, useValue : '/' }
    ]
})
Eyeleteer answered 20/9, 2017 at 17:49 Comment(0)
C
16

Angular 7,8 fix is in app.module.ts

import {APP_BASE_HREF} from '@angular/common';

inside @NgModule add

providers: [{provide: APP_BASE_HREF, useValue: '/'}]

Catnip answered 24/1, 2020 at 14:50 Comment(1)
I faced this error while trying to load a component for angular story book. This component had router dependency. It solved the error!!Siegel
M
12

You can also use hash-based navigation by including the following in app.module.ts

import { LocationStrategy, HashLocationStrategy } from '@angular/common';

and by adding the following to the @NgModule({ ... })

@NgModule({
  ...
  providers:    [
      ProductService, {
          provide: LocationStrategy, useClass: HashLocationStrategy
      }
  ],
  ...
})

Angular 2 Development with TypeScript

“HashLocationStrategy—A hash sign (#) is added to the URL, and the URL segment after the hash uniquely identifies the route to be used as a web page fragment. This strategy works with all browsers, including the old ones.”

Excerpt From: Yakov Fain Anton Moiseev. “Angular 2 Development with TypeScript.”

Middendorf answered 21/2, 2017 at 1:10 Comment(1)
Thanks Lionel! This is excellent and solved a problem I had using the APP_BASE_HREF solution above which fails when using url parameters like "product/:id". Thanks!Eyesight
C
8

Since 2.0 beta :)

import { APP_BASE_HREF } from 'angular2/platform/common';
Castleberry answered 12/5, 2016 at 13:23 Comment(2)
As of Rc6 this is all in the provider now: angular.io/docs/ts/latest/api/common/index/…Ozonize
This helped me when my spec in Karma was failing with Error: No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.Cigar
S
7

it is just that add below code in the index.html head tag

   <html>
    <head>
     <base href="/">
      ...

that worked like a charm for me.

Sibie answered 12/3, 2018 at 3:20 Comment(0)
S
6

With angular 4 you can fix this issue by updating app.module.ts file as follows:

Add import statement at the top as below:

import {APP_BASE_HREF} from '@angular/common';

And add below line inside @NgModule

providers: [{provide: APP_BASE_HREF, useValue: '/my/app'}]

Reff: https://angular.io/api/common/APP_BASE_HREF

Severance answered 2/2, 2018 at 12:20 Comment(1)
Why does useValue need to be '/my/app'?Eyeleteer
S
2

Check your index.html. If you have accidentally removed the following part, include it and it will be fine

<base href="/">

<meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
Shippen answered 25/2, 2019 at 7:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.