AngularJS <a> tag links not working

I have an index of objects returned from search. The template has an ng-repeat where the item's URL is constructed from data in the model but in the final markup the "a" tag does not work. The ng-href and href are correct, the URL bar changes when the link is clicked but the page does not load. Doing a browser refresh after the click does get the page. So something in Angular is changing the URL bar but not triggering a load???

Can't make this reproduce in a jsfiddle because the problem seems to be in loading the json into the template after a $resource.query() function, which I can't do from a jsfiddle. With a simulated query loading static data the jsfiddle works even though the final markup looks identical.

The AngularJS template looks like this:

<div ng-controller="VideoSearchResultsCtrl" class="row-fluid">
  <div class="span12" >
    <div class="video_thumb" ng-repeat="video in videos">
      <p>
        <a ng-href="/guides/{{video._id}}" data-method="get">
          <img ng-src="{{video.poster.large_thumb.url}}">
        </a>
      </p>
    </div>
  </div>
</div>

The results look fine and produce the following final markup:

<div ng-controller="VideoSearchResultsCtrl" class="row-fluid ng-scope">
  <div class="span12">
    <!-- ngRepeat: video in videos --><div class="video_thumb ng-scope" ng-repeat="video in videos">
      <p>
        <a ng-href="/guides/5226408ea0eef2d029673a80" data-method="get" href="/guides/5226408ea0eef2d029673a80">
          <img ng-src="/uploads/video/poster/5226408ea0eef2d029673a80/large_thumb_2101146_det.jpg" src="/uploads/video/poster/5226408ea0eef2d029673a80/large_thumb_2101146_det.jpg">
        </a>
      </p>
    </div><!-- end ngRepeat: video in videos -->
  </div>
</div>

The controller code is:

GuideControllers.controller('VideoSearchResultsCtrl', ['$scope', '$location', 'VideoSearch',
    function($scope, $location, VideoSearch) {
        $scope.videos = VideoSearch.query({ namespace: "api", resource: "videos", action: 'search', q: $location.search().q });
    }
]);

Using AngularJS 1.2-rc.3. I've also tried using an ng-click and regular old onclick to get a page loaded even with static URL but the clicks never trigger the code. BTW static non-angular links on this page do work, so the Menu Bar and Sign Out work.

What have I done wrong here or is this a bug in AngularJS?


Solution 1:

From the mailing list I got an answer:

Have you by any chance configured your $locationProvider to html5Mode? If yes this would cause your problems. You could force it to always go to the url by adding target="_self" to your tag. Give it a shot.

I had configured to use HTML5 so adding the target="_self" to the tag fixed the problem. Still researching why this works.

Solution 2:

Not sure if this has been updated since this post was answered, but you can configure this in application startup. Setting the rewriteLinks to false re-enables your a tags, but still leaves html5mode on, which comes with all its own benefits. I have added a bit of logic around these settings to revert html5mode in browsers where window.history is not supported (IE8)

app.config(['$locationProvider', function ($locationProvider) {

    if (window.history && window.history.pushState) {
        $locationProvider.html5Mode({
            enabled: true,
            requireBase: true,
            rewriteLinks: false
        });
    }
    else {
        $locationProvider.html5Mode(false);
    }
}]);

Angular Docs on $locationProvider

The benefits of html5mode vs hashbang mode

Solution 3:

I know this post is old, but I recently ran into this problem as well. My .html page had the base

//WRONG!
<base href="/page" />

and the fix:

//WORKS!
<base href="/page/" />

notice the forward-slash ('/') after 'page'.

Not sure if this applies to other cases, but give it a try!

Solution 4:

AngularJS suffers from a sparse documentation, I hope their gaining momentum will improve it. I think AngularJS is primarily intended as a SPA, and maybe the idea behind deactivating by default all a tags allows one to easily incorporate angular into some already existing html.

This allows for quick refactoring of the default "routing" behaviour of a "traditional" website (well, script pages linked between each other) into the angular routing system, which is more of an MVC approach, better suited for Web Apps.