1

Js:

myApp.directive('locationClass', function ($location) {

    return {
        restrict : 'A',
        link: function (scope, element) {
            var currentLocation = $location.path();

            var formatCurrentLocation = currentLocation.replace(/\//g, " ");

            //console.log(currentLocation);
            element.addClass(formatCurrentLocation);
    }

    }

});  

Html

<html ng-app="myApp" ng-controller="headerCtrl as header" location-class>  

it works corrrectly , but when pages load, it updated , when i change steps the value does not update .

Url Example: CounterForm/InstallCounter to CounterForm/CounterEquipment

I'm using Ui-router .
Any Idea ? Thanks

Sadeghbayan
  • 1,163
  • 2
  • 18
  • 38

2 Answers2

2

Your link function is called only once when the directive gets rendered.

This means that when your html was rendered for the first time, then only, the function was called. And so it did the work. When the url changes, you need listeners to update according to the changes.

It won't have live connections to the URL.

You need to create a listener on $locationChangeSuccess event in the link function. That should do your work.

Check here for documentation. Search for this function there. Then whenever you change your url, it will be called and the changes will be done. Your directive becomes like:

myApp.directive('locationClass', function ($location, $rootScope) {

    return {
        restrict : 'A',
        link: function (scope, element) {
            $rootScope.$on('$locationChangeSuccess', function () {
                var currentLocation = $location.path();

                var formatCurrentLocation = currentLocation.replace(/\//g, " ");

                //console.log(currentLocation);
                element.addClass(formatCurrentLocation);
            });

    }
}

UPDATE for the purpose of toggling classes:

You use a scope variable instead. We can just have a variable to store the class and put the variable on the html. Check the locationClass variable in the html.

So your html will be like :

<html ng-app="myApp" ng-controller="headerCtrl as header" location-class class="{{locationClass}}">  

and your directive, we modify as :

myApp.directive('locationClass', function ($location, $rootScope) {

    return {
        restrict : 'A',
        link: function (scope, element) {
            $rootScope.$on('$locationChangeSuccess', function () {
                var currentLocation = $location.path();

                var formatCurrentLocation = currentLocation.replace(/\//g, " ");
                scope.locationClass = formatCurrentLocation;

            });

    }
}

So now whenever you change your location, when the change is successful, the variable will be updated on the class attribute and your html will have new class. You don't need to remove the old class manually.

I think this will solve the problem and also it is a better way of doing stuff. We don't want to handle DOM directly unless necessary in AngularJS. If variable can do that, we do it.

UPDATE 2:(if you want to use watch):

We can keep a watch on location.path() and use that also to track the classname.

myApp.directive('locationClass', function ($location, $rootScope) {

    return {
        restrict : 'A',
        link: function (scope, element) {

            scope.$watch('$location.path()', function(currentLocation) {

                var formatCurrentLocation = currentLocation.replace(/\//g, " ");
                scope.locationClass = formatCurrentLocation;
            });

    }
}

But still I would recommend that you go for the listener on location change success. The reason being that the watch is heavy and will be triggered everytime the scope becomes dirty(means almost everytime if the scope is on body) whereas the event listener will call the function only when the url gets changed. You can put a console inside the function to check and verify this.

Kop4lyf
  • 4,520
  • 1
  • 25
  • 31
2

you have to watch your scope variable for change

return {
   restrict: 'A',
   scope: {
     name: '='
   },
   link: function($scope) {
     $scope.$watch('name', function() {
        // all the code here...
     });
   }
};

As per your example i think it will work

 scope.$watch('data', function(){ // replace data with variable on which you have to watch change
                var currentLocation = $location.path();
                var formatCurrentLocation = currentLocation.replace(/\//g, " ");
                element.addClass(formatCurrentLocation);
                $compile(element.contents())(scope);

            });

Keval Bhatt
  • 6,224
  • 2
  • 24
  • 40
  • 1+ thanks , what's that ? $compile(element.contents())(scope); – Sadeghbayan Jun 01 '15 at 13:04
  • you can use compile to link scope and the template together. if you have any variable which is present in your template or in html then to link scope of that variable we can use compile – Keval Bhatt Jun 01 '15 at 13:08
  • The compilation is a process of walking the DOM tree and matching DOM elements to directives. https://docs.angularjs.org/api/ng/service/$compile – Keval Bhatt Jun 01 '15 at 13:09
  • and one more question , how can i use data in your $watch ? – Sadeghbayan Jun 01 '15 at 13:09
  • data is just an example you have to use variable in which you want to watch change – Keval Bhatt Jun 01 '15 at 13:10
  • see this angular life cycle example http://tutorials.jenkov.com/angularjs/watch-digest-apply.html then you know how angular works – Keval Bhatt Jun 01 '15 at 13:11
  • would you please see this : http://stackoverflow.com/questions/12669674/how-to-update-angularjs-directive-when-url-is-changed the answer watch only $Location – Sadeghbayan Jun 01 '15 at 13:20
  • 1
    The watch is correct but @keval, you cannot keep compiling the whole directive. If it is a directive at some small element levet it makes total sense, but when you keep on compiling the whole body(see the directive position) on every location change, it is not recommended. Why? because, it will basically re-render all the elements which are static and have nothing to do with location changes and makes the application uncessarily heavy. – Kop4lyf Jun 02 '15 at 02:48