Home » Angularjs » Removing the fragment identifier from AngularJS urls (# symbol)

Removing the fragment identifier from AngularJS urls (# symbol)

Posted by: admin November 2, 2017 Leave a comment

Questions:

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 #?

Answers:

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);

  }]);

Questions:
Answers:

Be sure to check browser support for the html5 history API:

  if(window.history && window.history.pushState){
    $locationProvider.html5Mode(true);
  }

Questions:
Answers:

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
          });
        }
    }]);

Questions:
Answers:

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

Questions:
Answers:

If you are in .NET stack with MVC with AngularJS, this is what you have to do to remove the ‘#’ from url:

  1. Set up your base href in your _Layout page: <head> <base href="/"> </head>

  2. Then, add following in your angular app config : $locationProvider.html5Mode(true)

  3. 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"
    }
);

Questions:
Answers:

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.

Questions:
Answers:

Follow 2 steps-

1. 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.

Questions:
Answers:

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]

Questions:
Answers:

As has been mentioned in above answers the steps are-

Add to index.html
Enable html5mode $location.html5Mode(true) in app.js.

With this the application will work good. But only in the scenarios when you navigate from the index.html to other pages. For example my base page is- www.javainuse.com. If I click on link java it will correctly navigate to www.javainuse.com/java.

However if i directly go to www.javainuse.com/java will get page no found error.

To resolve this we have to use url rewriting. Dot net requires URL rewriting for IIS.

If you are using tomcat then URL rewriting will have to be done using Tuckey. Can get more information on URL rewriting here

Questions:
Answers:

According to the documentation. You can use:

$locationProvider.html5Mode(true).hashPrefix('!');

NB: If your browser does not support to HTML 5. Dont worry 😀 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

Questions:
Answers:

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>

Questions:
Answers:

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.

Questions:
Answers:

Just add $locationProvider In

.config(function ($routeProvider,$locationProvider)

and then add $locationProvider.hashPrefix('');
after

.otherwise({
        redirectTo: '/'
      });

That’s it.