1

Im trying to manipulate my table with angularjs using directives.

I want to add a new class to the first td with id=2 like this:

gameApp.directive('mapActivity', function() {
    return {
        link: function(scope, element, attrs) {
            angular.element('.click#1').addClass('dotted');
        }
    };
});

Im trying to "use" the drictive here:

<map-activity>
<table ng-bind-html="safeHtml()">
</table>
</map-activity>

But nothing happens. The first TD does not get the class 'dotted'. What do I do wrong?

Here is my controller:

var gameApp = angular.module("gameApp", ['ngRoute','ngSanitize']);

gameApp.service('link', function() {
    this.user = false;
});
gameApp.filter('unsafe', function($sce) {
    return function(val) {
        return $sce.trustAsHtml(val);
    };
});

gameApp.directive('mapActivity', function() {
    return {
        priority: 1,
        restrict: 'A',
        link: function(scope, element, attrs) {
            angular.element('.click#1').addClass('dotted');
        }
    };
});
function makeTableFrom(str) {
    var k = 1;
    result = "";

    for(var i = 1; i <= 8; i++) {
        result += '<tr>';

        for(var j = 1; j <= 20; j++) {
            if(str[k] == '#') {
                result += '<td id=' + k + '">#</td>';
            }
            else if(str[k] == '&') {
                result += '<td class="click" val="water" id="' + k + '">&</td>';
            }
            else {
                result += '<td class="click" id="' + k + '"><a href="#"></a></td>';
            }

            k++;
        }
        result += '</tr>';
    }
    return result;
}


gameApp.config(function($routeProvider) {
    $routeProvider

    .when('/', {
            templateUrl : 'partials/firstpage.html',
            controller  : 'firstPageCtrl'
    })

    .when('/game', {
            templateUrl : 'partials/game.html',
            controller  : 'gameCtrl'
    });

});

gameApp.controller("firstPageCtrl", function($scope,$http,link,$location) {
    $scope.doLogin = function() {
        $http.post("lib/action.php", {username: $scope.username, password: $scope.password}).success(function(data) {
            if(data) {
                link.user = data;
                console.log(link.user);
                $location.path("/game");
            }
        }).error(function(data) {
            console.log(data);
        });
    };
});


gameApp.controller("gameCtrl", function($scope,$http,link,$location,$sce) {
    //$scope.trr = [1,2,3,4,5,6,7,8];
    //$scope.tdd = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
    $scope.getMonsters = "1";
    var map;

    $http.post("lib/action.php", {monsters: $scope.getMonsters}).success(function(data) {
        map = data;
        console.log(map);
        $scope.result = makeTableFrom(data);
        console.log($scope.result);
    });

    $scope.safeHtml = function() {
        return $sce.trustAsHtml($scope.result);
    };
    if(link.user) {
        /*$scope.message = "fisk";
        console.log(link.user);*/
    } else {
        /*$scope.message = "Ledsen fisk";
        console.log("Är inte satt");*/
    }

});

As you can see, Im using a javascript function to assaign a variable witht the HTML, and then using this in my view, passing it through a filter.

When I hit Ctrl+u to view the source of the page, I can't see the td's and tr's that is being printed out. Can this affect why it's not working?

2
  • create jsfiddle with your code please. Commented Aug 18, 2014 at 13:28
  • Are you sure your directive code is triggered after table content is filled out? Maybe you try to add class to non-existing element, and then table is filled in. Possibly add $timeout with 0 to your directive, so it gets the content first. Commented Aug 18, 2014 at 13:29

3 Answers 3

1

Try assigning different priority to map-activity directive, so it would process after ng-bind-html

And as both @Abhishek Jain and @Dalorzo pointed out , your directive has to be attribute applied to the same DOM element

.directive('mapActivity', function() {
    return {
       priority: 0,   // check what priority ng-bind-html have and set it to be more than that.
       link: function(scope, element, attrs) {
          ...
       }
    }
})

priority

When there are multiple directives defined on a single DOM element, sometimes it is necessary to specify the order in which the directives are applied. The priority is used to sort the directives before their compile functions get called. Priority is defined as a number. Directives with greater numerical priority are compiled first. Pre-link functions are also run in priority order, but post-link functions are run in reverse order. The order of directives with the same priority is undefined. The default priority is 0.

Sign up to request clarification or add additional context in comments.

6 Comments

How do I set a priority to my directive?
I attached link - it is property of object that you return from directive. Updated my answer.
Priority only applies to directives at the same element level. Unless the directive is an attribute at table level modifying the priority won't have any effect. It is mentioned on the shared linked btw
@user500468 you are asking the wrong question. Setting a priority will not help you in any way in this case. The problem in your case is that the directive is not used at the right place.
@Dalorzo you are right, both directives have to be on the same element
|
1

You need to add the directive to the tag you want to attach it to. In your directive declaration, you have declared myDirective as an attribute directive, but you are using it as an element directive in your html.

Assuming .click#1 selector corresponds to the first td and you want the directive to be an attribute, you need to do this:-

<table ng-bind-html="safeHtml()" map-activity>

Edit:-

If you want to target first td of every row, You can just define your directive like this:-

app.directive('mapActivity', [function(){
   return {
        restrict: 'A',
        link: function($scope, iElm, iAttrs, controller) {
            iElm.find('tr td:first-of-type').addClass('dotted');
        }
    };
}]);

2 Comments

I belive you meant <table ng-bind-html="safeHtml()" map-activity>
Oh yes, sorry for the typo and thanks for correcting!! :-) I have edited the answer.
0

What you are doing it is a bit odd since what you are doing is creating a new element instead of modifying your current table element with an attribute, like:

<table ng-bind-html="safeHtml()" map-Activity="">
</table>

Then:

gameApp.directive('mapActivity', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
           scope.$watch(attr.ngBindHtml, function(value) {
              angular.element('.click#1').addClass('dotted');                              
           });
        }
    };
});

Additionally make sure you specify to what type of directive is using the restrict attribute A= Attribute, E= Element, C= Class,... Those can be combined restrict: 'EAC',

The link function in your sample version will be executed first and additionally some browsers will have difficulties understanding unknown elements it is because of this that it may be better to move at table level your directive.

4 Comments

@Dolarzo: Table level? How do I set the prority of the my directive so that the ng-bind-html is executed first?
last time I checked ng-bind used priority:100 and it only applies to directives at the same element level. Unless you move your directive to be an attribute at table level modifying the priority won't have any effect
Thank you. However, it don't work. How Can I see if the directive is loaded or even used? Can it have something to do with how I fill my table with my td's and rows? Check the updated version of my question to see how I fill my table with the td's and tr's
No it seems to work when you added scope.$watch. What is that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.