Removing the fragment identifier from AngularJS urls (# symbol)
AngularjsUrlNgrouteAngularjs Problem Overview
Is it possible to remove the # symbol from angular.js URLs?
I still want to be able to use the browser's back button, etc, when I change the view and will update the URL with params, but I don't want the # symbol.
The tutorial routeProvider is declared as follows:
angular.module('phonecat', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
}]);
Can I edit this to have the same functionality without the #?
Angularjs Solutions
Solution 1 - Angularjs
Yes, you should configure $locationProvider
and set html5Mode
to true
:
angular.module('phonecat', []).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/phones', {templateUrl: 'partials/phone-list.html', controller: PhoneListCtrl}).
when('/phones/:phoneId', {templateUrl: 'partials/phone-detail.html', controller: PhoneDetailCtrl}).
otherwise({redirectTo: '/phones'});
$locationProvider.html5Mode(true);
}]);
Solution 2 - Angularjs
Be sure to check browser support for the html5 history API:
if(window.history && window.history.pushState){
$locationProvider.html5Mode(true);
}
Solution 3 - Angularjs
To remove the Hash tag for a pretty URL and also for your code to work after minification you need to structure your code like the example below:
jobApp.config(['$routeProvider','$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'views/job-list.html',
controller: 'JobListController'
}).
when('/menus', {
templateUrl: 'views/job-list.html',
controller: 'JobListController'
}).
when('/menus/:id', {
templateUrl: 'views/job-detail.html',
controller: 'JobDetailController'
});
//you can include a fallback by including .otherwise({
//redirectTo: '/jobs'
//});
//check browser support
if(window.history && window.history.pushState){
//$locationProvider.html5Mode(true); will cause an error $location in HTML5 mode requires a tag to be present! Unless you set baseUrl tag after head tag like so: <head> <base href="/">
// to know more about setting base URL visit: https://docs.angularjs.org/error/$location/nobase
// if you don't wish to set base URL then use this
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
}
}]);
Solution 4 - Angularjs
I write out a rule in web.config after $locationProvider.html5Mode(true)
is set in app.js
.
Hope, helps someone out.
<system.webServer>
<rewrite>
<rules>
<rule name="AngularJS" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
In my index.html I added this to <head>
<base href="/">
Don't forget to install url rewriter for iis on server.
Also if you use Web Api and IIS, this match url will not work out, as it will change your api calls. So add third input(third line of condition) and give out a pattern that will exclude calls from www.yourdomain.com/api
Solution 5 - Angularjs
If you are in .NET stack with MVC with AngularJS, this is what you have to do to remove the '#' from url:
-
Set up your base href in your _Layout page:
<head> <base href="/"> </head>
-
Then, add following in your angular app config :
$locationProvider.html5Mode(true)
-
Above will remove '#' from url but page refresh won't work e.g. if you are in "yoursite.com/about" page refreash will give you a 404. This is because MVC does not know about angular routing and by MVC pattern it will look for a MVC page for 'about' which does not exists in MVC routing path. Workaround for this is to send all MVC page request to a single MVC view and you can do that by adding a route that catches all
url:
routes.MapRoute(
name: "App",
url: "{*url}",
defaults: new {
controller = "Home", action = "Index"
}
);
Solution 6 - Angularjs
You can tweak the html5mode but that is only functional for links included in html anchors of your page and how the url looks like in the browser address bar. Attempting to request a subpage without the hashtag (with or without html5mode) from anywhere outside the page will result in a 404 error. For example, the following CURL request will result in a page not found error, irrespective of html5mode:
$ curl http://foo.bar/phones
although the following will return the root/home page:
$ curl http://foo.bar/#/phones
The reason for this is that anything after the hashtag is stripped off before the request arrives at the server. So a request for http://foo.bar/#/portfolio
arrives at the server as a request for http://foo.bar
. The server will respond with a 200 OK response (presumably) for http://foo.bar
and the agent/client will process the rest.
So in cases that you want to share a url with others, you have no option but to include the hashtag.
Solution 7 - Angularjs
Follow 2 steps-
- First set the $locationProvider.html5Mode(true) in your app config file.
For eg -
angular.module('test', ['ui.router']) .config(function($stateProvider, $urlRouterProvider, $locationProvider) { $locationProvider.html5Mode(true); $urlRouterProvider.otherwise('/'); });
2.Second set the <base> inside your main page.
For eg ->
<base href="/">
The $location service will automatically fallback to the hash-part method for browsers that do not support the HTML5 History API.
Solution 8 - Angularjs
My solution is create .htaccess and use #Sorian code.. without .htaccess I failed to remove #
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^(/index\.php|/img|/js|/css|/robots\.txt|/favicon\.ico)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ./index.html [L]
Solution 9 - Angularjs
According to the documentation. You can use:
$locationProvider.html5Mode(true).hashPrefix('!');
> NB: If your browser does not support to HTML 5. Dont worry :D it have
> fallback to hashbang mode. So, you don't need to check with if(window.history && window.history.pushState){ ... }
manually
For example: If you click: <a href="/other">Some URL</a>
In HTML5 Browser:
angular will automatically redirect to example.com/other
In Not HTML5 Browser:
angular will automatically redirect to example.com/#!/other
Solution 10 - Angularjs
This answer assumes that you are using nginx as reverse proxy and you already did set $locationProvider.html5mode to true.
->For the people who might still be struggling with all cool stuff above.
Surely, @maxim grach solution works fine, but for the solution for how to respond to requests that doesn't want the hashtag to be included in the first place what can be done is check if php is sending 404 and then rewrite the url. Following is the code for nginx,
In the php location, detect 404 php error and redirect to another location,
location ~ \.php${
...
fastcgi_intercept_errors on;
error_page 404 = /redirect/$request_uri ;
}
Then rewrite url in redirect location and proxy_pass the data, offcourse, put your website url at the place of my blog's url. (Request : Question this only after you tried it)
location /redirect {
rewrite ^/redirect/(.*) /$1;
proxy_pass http://www.techromance.com;
}
And see the magic.
And it definitely works, atleast for me.
Solution 11 - Angularjs
Start from index.html remove all #
from <a href="#/aboutus">About Us</a>
so it must look like <a href="/aboutus">About Us</a>
.Now in head tag of index.html write <base href="/">
just after last meta tag.
Now in your routing js inject $locationProvider
and write $locatonProvider.html5Mode(true);
Something Like This:-
app.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when("/home", {
templateUrl: "Templates/home.html",
controller: "homeController"
})
.when("/aboutus",{templateUrl:"Templates/aboutus.html"})
.when("/courses", {
templateUrl: "Templates/courses.html",
controller: "coursesController"
})
.when("/students", {
templateUrl: "Templates/students.html",
controller: "studentsController"
})
$locationProvider.html5Mode(true);
});
For more Details watch this video https://www.youtube.com/watch?v=XsRugDQaGOo
Solution 12 - Angularjs
Guess this is reallllly late for this. But adding the below config to the app.module imports does the job:
RouterModule.forRoot(routes, { useHash: false })
Solution 13 - Angularjs
Step 1: Inject the $locationProvider service into the app config's constructor
Step 2: Add code line $locationProvider.html5Mode(true) to the app config's constructor.
Step 3: in the container (landing, master, or layout) page, add html tag such as <base href="/">
inside the tag.
Step 4: remove all '#" for routing config from all anchor tags. For examples, href="#home" becomes href="home"; href="#about" becomes herf="about"; href="#contact" becomes href="contact"
<ul class="nav navbar-nav">
<li><a href="home">Home</a></li>
<li><a href="about">About us</a></li>
<li><a href="contact">Contact us</a></li>
</ul>
Solution 14 - Angularjs
Just add $locationProvider
In
.config(function ($routeProvider,$locationProvider)
and then add $locationProvider.hashPrefix('');
after
.otherwise({
redirectTo: '/'
});
That's it.