10

If I have a one level route, then the hash links work as expected with no rerouting. However I have some urls that are country/kh and if I try using hash tags such as country/kh#projects, the page reroutes, which is very annoying.

So, if im on page countries and click the link #developing, then the page will scroll to #developing without rerouting, which is desired. If I'm on page country/kh and I click #projects, the page will reroute, then scroll to #projects; I don't want the rerouting to occur.

The issue only occurs for links of the nature page1/parameter#anchor, not for simple pageA#anchor.

Sophie McCarrell
  • 2,831
  • 8
  • 31
  • 64
  • 1
    country?country=kh#projects should be country#projects?country=kh – dave Apr 16 '14 at 20:30
  • That makes sense, but the issue still occurs. Let me edit the question. Thanks for point that out though. – Sophie McCarrell Apr 16 '14 at 20:33
  • 1
    @JasonMcCarrell: It is not very clear how your setup looks like. It would help to prepare a little fiddle that demonstrates the issue. – gkalpak May 23 '14 at 05:31
  • Just a random FYI. Still is still an issue for me, even after nearly a year. I have a sidebar that reroutes every time they click to go to a different hash. The urls are simply "#projects" etc. They don't contain the full url, yet they still redirect. – Sophie McCarrell Dec 13 '14 at 03:54
  • Did you consider using the html5 style in angular ? there would bge no hashbang anymore – sam Dec 17 '14 at 15:34

4 Answers4

5

It is very difficult to answer your question without any code samples or a plunker. I implemented a plunker code ( http://plnkr.co/edit/oflB21?p=preview ) to try to reproduce this issue but as you can see I could not reproduce the issue. i.e. You can easily navigate back and forth between two different sections of the page, e.g. between #/Country/Italy#Section-4 and #/Country/Italy#Section-1, without any page load or reroute. Please check out my working example at the following plunker. This most probably is happening to you due to a missing hash bang or forward slash or details like that.

HTML snippet for the home page:

<ul>
    <li><a href="#/Country">Go to /Country</a></li>
    <li><a href="#/Country/US">Go to /Country/US</a></li>
    <li><a href="#/Country/Italy#Section-4">Go to /Country/Italy#Section-4</a></li>
    <li><a href="#/Country/Canada#Section-8">Go to /Country/Canada#Section-8</a></li>
</ul>

HTML snippet for the country page:

<div id="Section-1" class="section pink">
    Section 1
    <div ng-if="country">
        <a ng-href="#/Country/{{country}}#Section-8">Go to /Country/{{country}}#Section-8</a>
    </div>
    <div ng-if="!country">
        <a ng-href="#/Country#Section-8">Go to /Country#Section-8</a>
    </div>
</div>

All the JavaScript code:

var app = angular.module("app", ["ngRoute"]);

app.config(["$routeProvider", "$locationProvider", 
    function ($routeProvider, $locationProvider) {
    $routeProvider
    .when("/", {
        templateUrl: "./home-page.html",
        caseInsensitiveMatch: true,
    })
    .when("/Home", {
        templateUrl: "./home-page.html",
        caseInsensitiveMatch: true,
    })
    .when("/Country", {
        templateUrl: "./country-page.html",
        caseInsensitiveMatch: true,
    })
    .when("/Country/:country", {
        templateUrl: "./country-page.html",
        caseInsensitiveMatch: true,
    })
}]);

countryController.$inject = ["$scope", "$routeParams", "$location", "$anchorScroll"];
function countryController($scope, $routeParams, $location, $anchorScroll) {

    $scope.country = $routeParams.country;

    if (!!$location.$$hash) {
        $location.hash($location.$$hash);
        $anchorScroll();
    }
}
yoniLavi
  • 2,624
  • 1
  • 24
  • 30
Aidin
  • 2,134
  • 22
  • 26
3

Alright, I believe the main issue is that Angular handles routing with hashes (sometimes). What you need to do is use the $anchorScroll service. So your JS would look something like:

function ScrollCtrl($scope, $location, $anchorScroll) {
  $scope.gotoBottom = function (){
    // set the location.hash to the id of
    // the element you wish to scroll to.
    $location.hash('bottom');

    // call $anchorScroll()
    $anchorScroll();
  };
}

And then your HTML could be:

<div id="scrollArea" ng-controller="ScrollCtrl">
  <a ng-click="gotoBottom()">Go to bottom</a>
  <a id="bottom"></a> You're at the bottom!
</div>

http://plnkr.co/edit/De6bBrkHpojgAbEvHszu?p=preview - this is a plunkr (not mine) that demonstrates using $anchorScroll if you need to see it in action

dave
  • 62,300
  • 5
  • 72
  • 93
  • But the hashes work if I'm in a single level url like /countries#section1. It's just that they reroute during /country/hk#section1, when I don't want them to reroute. I'm simply trying to prevent the route, while maintaining the use of the href attribute (so it's consistent with the rest of hte pages... and the non-angular internet =P). – Sophie McCarrell Apr 17 '14 at 11:06
  • This is what I had to use. This is not the solution i want, but you giving me a work around. I'll wait to see if there is any response to the comment i wrote on the other answer, before I choose this one as the correct answer. Thanks. – Sophie McCarrell Jan 23 '15 at 06:49
1

There's a dead-simply solution to your problem...

Instead of doing:

    <a href="page1/parameter#anchor">go</a>

Just do

    <a href="#anchor">go</a>

I suspect the reason for the unexpected behavior is a bug/feature of whatever routing solution you are using (ie the built-in angular router, or ui-router or whatever). ui-router has a way to disable re-routing when going to the same route...

Gil Birman
  • 35,242
  • 14
  • 75
  • 119
  • 1
    Doesn't work. Good try, but that was actually the first way I wrote the urls. I initially didn't include the full url. Angular still tries to build the full url, then screws up. – Sophie McCarrell May 28 '14 at 12:51
1

I think I had the same problem that you are having.

This is how I did it with my github page, http://ngmap.github.io.

Th site, http://ngmap.github.io, has many pages and each page has lots of anchors, all anchors are coded naturally.

Without the following code of http://ngmap.github.io/javascripts/app.js, when you click an anchor in your page;

  • it sets $location.path to /anchor. i.el http://url.com/#anchor
  • and it sets $location.hash to ``.

This behaviour will prevent the page from scrolling down to the hash because simply there is no hash in the url.

By simply adding $location.hash and scrolling down to that anchor, all should work.

 /**
   * when the location is changed, scroll the page to the proper element.
   * by changing location hash from '' to 'hash', so that it can be used as $anchorScroll
   */
  $rootScope.$on('$locationChangeSuccess', function(newRoute, oldRoute) {
    $location.hash($location.path().replace(/^\//,"")); 
    $anchorScroll();  
  });

With the above code,

  • $location.path remains the same, /anchor
  • $location.hash now becomes anchor

The only thing you may not like is, the url. It looks little dirty, but I did not mind.

i.e. http:/ngmap.github.io/basics.html#/map-geolocation#map-geolocation

Hope it helps

allenhwkim
  • 27,270
  • 18
  • 89
  • 122