I am trying to configure angular routing using $routeProivder
So I have
$routeProvider
.when('/title', {
templateUrl: 'views/title.html',
})
.when('/title/article-name', {
templateUrl: 'views/article-name.html',
})
However, with $locationProvider.html5Mode(true), It will find the page template but every links image js css file will not be found, therefore my layout is screwed ( My header and footer are in my index.html, template is rendering from ng-view ). Also when I click on the links it shows "Cannot get /title/article-name/sample.js"
My question is how do I do multi level routing with angular.
so like "www.domain.com/why-us/our-company/our-goal" something like that. Thanks
On top of setting html5Mode(true), you will need to set up your server to support the cool URLS in HTML5 mode. See explanation from official AngularJS documentation below:
Server side
Using this mode requires URL rewriting on server side, basically you have to rewrite all your links to entry point of your application (e.g. index.html)
What it means is that you need to redirect any static resource to the starting point of your application.
Let's say your sample.js is on the root of your site www.domain.com.
The server needs to rewrite the URL for this file to point to http://www.domain.com/sample.js instead of http://www.domain.com/title/article-name/sample.js
There are different ways to do it on the server side depending on which type of server you are using. On common approach to do this is serve all the static resources from the URLS with the /static prefix and tell the server to rewrite all links to this folder.
On the client side I saw some solutions using <base href="/" /> inside the <head>.
The HTML < base > element specifies the base URL to use for all relative URLs contained within a document.
You could give try and see if it works for you - just keep in mind that because is on the client side, you need to see the cross browser support for this.
I personally would suggest the server side solution.
<html>
<head>
<base href="/" />
</head>
....
</html>
Related
I am using Angularjs to build a web app but I am getting http://localhost:3000/#!/ instead of http://localhost:3000/ when I go to my index page.
I couldn't figure out why it's happening.
Some help would be great.
The hashBang #! is usually added by angularjs between the url and the angular routes. You can disable it in the .config() using $locationProvider and setting the html5Mode to true like so :
.config('$locationProvider', function($locationProvider){
$locationProvider.html5Mode(true);
})
Using HTML5 mode requires URL rewriting on server side, basically you have to rewrite all your links to entry point of your application (e.g. index.html). Requiring a <base> tag is also important for this case, as it allows AngularJS to differentiate between the part of the url that is the application base and the path that should be handled by the application. For more information, see AngularJS Developer Guide - HTML5 Mode Server Side.
I'm using Spring Boot 1.4.0.M2, Angular 1.5.8, Angular UI Router 0.3.1, and Thymeleaf templating.
What I want to do is to remove hash # from my url I want to something like this:
http://localhost:8080/#/contact
look like this
http://localhost:8080/contact
What I did:
added to my angular configuration.js file something like this:
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix('!');
added to my userIndex.html head
base href="/userIndex.html"/>
This userIndex.html contains all js libraries, this is my single page index page it contains imports like this:
<script type="text/javascript" th:src="#{/js/lib/jquery.min.js}" />
and UI router:
<div ui-view="" class="ui-container"></div>
After this hash # disappear from URL, but!
I open my web page http://localhost:8080/ than click link to for example "/contact" and go to sub page URL look perfect http://localhost:8080/contact no hash and page look like this.
And that when I press F5 to reload web page http://localhost:8080/contact and than content look like this:
Starting from http://localhost:8080/ and clicking link to /contact make everything ok, trying to enter URL http://localhost:8080/contact present raw html without css, js etc. userIndex.html is not loaded is it possible to load it to sub page like /contact?
This is how my project and template config looks like
Is any body here who could help me to fix this reload thing? Maybe it is something wrong with my spring boot template config?
The difference between the two ways is that in the first case you download the userIndex.html file and afterwards angular is intercepting your location change on client side to render the contact state.
In the second case, you are requesting the contact path from the server directly. This is where your viewController configuration comes into play and returns the probably not wanted html instead of the index page which would be required to run your angular app.
For node.js there is a concept called historyApiFallback that registers a 404 error handler to return the index.html page (e.g. this express module: https://github.com/bripkens/connect-history-api-fallback). In your case you need to avoid the clash between your registered viewControllers and the routing names used in the angular app. See this question for a similar case: How can I use Angular2 PathLocationStrategy in a Spring Boot application?
All in all it's not that convenient to use the PathLocationStrategy / html5Mode even if it is essential if you later want to have the possibility to also do server side rendering.
You need to configure server side routing. So when you removed the hash and you could go to the contact and it worked, but when you refreshed it lost the content because after refreshing the page your server tried to find contact.html and if it find in your case it served only that without the css and other stuff. Depend's on your server you can configure your server to fallback to index.html all the time so when it can not find the requested page. and set base to / otherwise server will go to the root of directory and find the contact.html and serve it to you and it will be raw without css. I hope i could explain it to you. You can search for the url-re-writer for your server.
I'm asking this because a couple of times now, I've tried to play around with the $locationProvider.html5Mode(true) command along with <base href="/"> and ran into a lot of errors calling the scripts/styles/images for my project. I guess there must be something I am doing wrong, but is there a certain folder structure you should follow so you don't run into these errors? Or is there a specific way that the base href works that I'm not quite understanding?
Recently, I thought I'd try it on a very, very small app. It's effectively a static website, but I want to take advantage of Angular's routing to make sure all of the pages can load instantly. So my structure would be something like this:
my-project
css
images
js
angular
app.js
app.routes.js
mainCtrl.js
views
home.html
about.html
contact.html
index.html
So I know that this folder structure isn't great, but I'll only be using Angular in this project for routing, nothing more, so it fits my needs.
I put into the head <base href="/">, put in body ng-app and ng-controller, and inside the body put a <div ng-view> somewhere too.
I added in the $locationProvider.html5Mode(true) and tried the app out. All of my scripts are then being loaded as http://localhost:8888/script.js which is incorrect. The project is located in a folder so that index.html is located in http://localhost:8888/my-project/index.html. So, it should be loading the scripts from http://localhost:8888/my-project/js/angular/app.js for example.
Is there something that I'm not understanding about the base href? Eventually I may host this app somewhere online, so I want the URLs to scripts etc to all be relevant to the file really. Anyone have any ideas?
Alright, so above the base href tag I would have my CSS styles which would be linked as css/style.css and at the bottom of my body tag I would have my scripts loaded as js/init.js or js/angular/app.js for example. This would try to load it as if the js folder is located directly at localhost:8888/js.
The Angular framework is a Single Page Application (SPA) that is able to run in a browser by essentially tricking the browser into running code snippets rather than make server calls, by making use of the "hash" (#) page anchor. Normally, a URL with a # would jump to a specific anchor point in the page; in the case of Angular or other similar SPA frameworks, the # is redirected to a code segment instead.
Ideally, you would like to not have to reference this # in your page URLs. This is where Html5Mode comes into play. Html5Mode is able to hide the #, by using the HTML5 Push State (aka history API).
When Html5Mode is enabled, the normal links on the page are silently replaced by Angular with event listeners. When these events are triggered, the current page is pushed into the browser history, and the new page is loaded. This gives the illusion that you are navigating to a new page, and even allows for the back button to operate.
This is all fine when you are dealing with links which are clicked from within the running application, but relying on event listeners can't work if you navigate to the page from an external source, where Angular isn't loaded into memory yet. To deal with this, you must be loading your pages from a web server which supports URL rewrites. When the server receives a request for a URL that there isn't a physical page for, it rewrites the URL to load the base HTML page, where Angular can be loaded and take over.
When Angular receives a request for a route which has been rewritten in this manner, it must first determine what the intended route was. This is where the Base HTML Tag comes into play. Angular uses the Base reference to help it to determine which part of the URL is on the server, and which part is a client route. Essentially, where the # in the URL would be if Html5Mode was not enabled.
Unfortunately, Base is an HTML Tag that is used by the browser for more than just Angular. The browser also uses this tag to determine the correct location to load scripts and resources using relative paths from, regardless of the path in the location bar. In general, this isn't a problem if all of the scripts and resources are relative to the location of the Index.html file. When Base is omitted, the browser will load scripts from the apparent base path determined by the current URI. However, once you provide it, the browser will use whatever value you have supplied.
In general, unless you are hosting angular on a sub-page of your site and you want your users to expect something specific in the URL string, you should always control the base on your server, and use Base="/" on the client side.
If I migrate a site to use angular and the ui-router. The URLs will now have .../#!/... in the address. Any existing links on social media etc pointing to elements with IDs i.e. www.my-website.com/#help will no longer work. Angular will redirect the URL to the root address.
Its a single page site so retaining the element addressing is important.
Does anyone know how to support the old urls in the new site?
You can use HTML5mode. This lets Angular change the routing and URLs of pages without refreshing the page (and without the '#'). Here's how, briefly:
In your app config function use:
$locationProvider.html5Mode(true); to turn on HTML5 mode.
Add base tag to your HTML head:
<base href="/" />
You server needs to be configured: See How to: Configure your server to work with html5Mode.
Is it possible to add a base url to all routes in an AngularJS app? Essentially changing its location on the server (kind of, if that makes sense... so it would be accessed not via / but via /something/).
To add some context, I am trying to place an existing Angular app behind some authentication such that the app would now be accessed at address say http://mysite/secure after successful login.
The problem is if I was to load the app at http://mysite/secure it works fine (the server will obviously serve up the correct page), but clicking any link would result in a page reload and route to http://mysite/#newpage instead of http://mysite/secure/#newpage.
Without adding /secure/ to all of the routes and link element is this possible? Cheers, sorry if that is not worded well.
The location for the base href must have trailing /. For example:
<base href="location" />
will not work. It must be in this format:
<base href="location/" />
Setting the <base> HTML5 tag might help. From the documentation here:
Relative links
Be sure to check all relative links, images, scripts etc. You must either specify the url base in the head of your main html file (<base href="/my-base">) or you must use absolute urls (starting with /) everywhere because relative urls will be resolved to absolute urls using the initial absolute url of the document, which is often different from the root of the application.
Running Angular apps with the History API enabled from document root is strongly encouraged as it takes care of all relative link issues.