2

I want to be able to use part of the URL in a controller, in this case to be able to set a body class based on the URL, but I would also like to use a service to fetch other information from a json file based on that URL.

If I use console.log to check what's in $scope.pageDetail.id withing the for loop, I get the correct response, but it returns "undefined" outside of the for loop. Everything works on page reload, but not when I use the page's navigation to click my way through the urls.

My controller:

oddproto.controller('UrlController', function($scope, $location, PageService){

  // Get page id from URL
  var pageId  = $location.path().replace("/", "");

  $scope.pageDetail = PageService.query(function(data) {
    // Get the correct page details from the dataset
    for (var i = 0; i < data.length; i++) {
      if (data[i].id === pageId) {
        $scope.pageDetail = data[i];
        break;
      }
    }
  });

})

My service

oddproto.factory('PageService', function($resource) {
  return $resource('includes/pages.json');
});

pages.json

[
  {
    "id": "blog",
    "name": "Blogg"
  },
  {
    "id": "cases",
    "name": "Projekt"
  },
  {
    "id": "contact",
    "name": "Kontakt"
  }
]

I've also tried doing this entirely without the service, i.e.

$scope.pageDetail = $location.path().replace("/", "");

But that only works on page load as well, so it seems to me like $location is the issue here. I don't know what else I can use though.

Adam Gerthel
  • 663
  • 3
  • 9
  • 24

2 Answers2

4

Your controller is not recognizing the location change. When the controller is initialized, it sets the page id, but after changing, your controller is not re-initialized. For this, you should use

scope.location=$location;
scope.$watch('location.path()', function(path) {
  $scope.pageDetail = ....
});

This will observe location.path() and if its changing, it does your custom magic.

Furthermore, I suggest you to make your controller to be a directive, as it is only dealing with styling your body-tag.

kfis
  • 4,739
  • 22
  • 19
  • I can't get it working using $watch as your example states, probably because I'm not sure how to use it (I'm having a hard time grasping it even after reading the docs). I tried something simple and left out the service and used: `$scope.$watch('location.path()', function(path) { $scope.pageDetail = $location.path().replace("/", ""); });` But that didn't update the controller either. $scope.pageDetail still only returns the inital page load path. – Adam Gerthel May 15 '13 at 16:19
  • well, I don't know, what might be the problem in your specific case, but I use something like this, I coded some tome ago and it works :S http://stackoverflow.com/questions/12592472/how-to-highlight-a-current-menu-item-in-angularjs/12631074#12631074 – kfis May 16 '13 at 00:13
  • Ahh, after reading my own post, I realized, you have to add the location to the scope, to be observed via scope scope.location=$location; Updated my answer – kfis May 16 '13 at 12:16
1

I got it working using $routeChangeSuccess

  $scope.$on('$routeChangeSuccess', function() {
    $scope.pageId = $location.path().replace("/", "");
  })

There might be an issue in angular using $watch for in regards to $location

Adam Gerthel
  • 663
  • 3
  • 9
  • 24
  • My bad, if you want to watch something on the scope, you have to add it to the scope before – kfis May 16 '13 at 12:17
  • Ok, I have a working solution now, but I did learn a lot about $watch thanks to you. I'll see if I make a new go at using $watch again instead of $routeChangeSucess. $watch is a lot more powerful – Adam Gerthel May 16 '13 at 13:53