Understand the Angular Base href Requirement

John Lindquist
InstructorJohn Lindquist

Share this video with your friends

Send Tweet
Published 6 years ago
Updated 3 years ago

The <base href=”/”/> you define will determine how all other assets you plan on loading treat their relative paths. While you’ll most often use / as your base href, it’s important to understand what’s going on in case you need to change how you’re hosting your project.

[00:00] So far our navigation has worked just fine with home, contacts, and contact 1, but as soon as I try and navigate to contact 2, you'll see this just hangs because it can't load our app.

[00:13] What's happening with this? If you see an error like this, and I'm using system JS to load this, it means it tried to load in my app using system JS but what got returned was an HTML file. That's because just like any other single-page application, this is always returning an index HTML.

[00:33] What's happening here is it's trying to load from this URL, from /2. It's trying to load my app from contacts/app, which you'll see in here is contacts/app return the index.html, which is definitely not what we want.

[00:52] The reason that happened is because our base href is set to ./. I'm doing this because I'm sharing these examples on Plunker so you guys can play with them embedded. What happens if I delete this? I'll hit save. I'll try and navigate back to the root again.

[01:10] Now, I'll get a huge explosion of errors in the console saying that a base ref is not set -- no base href found. I either need to define this in my index HTML or configure it with a token. The solution that's going to work for us is just in my HTML if I create this base and I assign it to /. That just means use the root of my server to load any of these things.

[01:37] If I go to contacts, contact 1 and now contact 2, and I hit enter, it's going to be just fine because now when it hits contacts 2 and it tries to load this app file, you'll see it loads this system.js config.

[01:50] It knows that app file is really main.ts and it confined that /app/main.ts doesn't get lost in the weeds of /contact anymore because it knows to look back up to the / right after the root of the server, which is 8080.

[02:04] You'll also notice right now that the styling is gone. That's because your href needs to be set or this base href needs to be set before anything else that uses the URLs. That includes any sort of style sheets.

[02:17] If I paste this here and hit save, now you'll see that this will load with a proper styling with my Arial font set because it could find the style sheet. Otherwise, it would have tried to load that style sheet from /contacts instead of just /.

[02:32] This covers the 99 percent scenario, just the / saying the root of the server is where I want to host everything from. I'd like to explain this scenario where I'm hosting this locally for recording but I'm also hosting it on Plunker so you can play with it embedded.

[02:47] That's actually going to require me to write some logic in here. I'm going to say my path will check the document location href. If the href includes Plunker anywhere in the URL, then we want the path to be relative, so ./otherwise -- let's format this a bit -- we want the path to be just absolute to the root of the server.

[03:11] That's just because Plunker hosts from a current directory, not from the root of Plunker while we're hosting from the root. From here, I can just say document right so drop the base href tag in here. This is just a string. I'm going to concatenate that path in there, path plus that, end of the string.

[03:32] When I hit save, you'll see everything goes back to working just fine. I get my style sheets. I'm now able to go to /two. This will load up just fine, the contacts 2, contacts home. It loads the styles fine and everything. This will also account for the case that I want to host this demo on Plunker.

~ 6 years ago

Can you target a child router-outlet? I have a base template that has a router-outlet for my app as a whole. When a user logs in, I load a SecureComponent in that base router-outlet. The SecureComponent has a template with nav links in it and another router-outlet. When I click on the nav links in the SecureComponent's nav links it loads the respective component in the base router-outlet instead of the router-outlet in the SecureComponent. Is there any way I can tell the routerLink attribute to target the secure component's router-outlet instead of the base router-outlet?

I have a simple example here: (Example)[https://plnkr.co/edit/YxidcgAJaNjlrQnINnmw?p=preview]