2

I have a simple Angular directive that adds a CSS class to an element when being clicked:

.directive("addClass", function () {
    return {
        scope: {
            name: "=addClass"
        },
        link: function (scope, element, attributes) {

            element.on("click", function () {
                element.addClass(scope.name);
                console.log("Element activated");
            });

            element.on("mouseleave", function () {
                element.removeClass(scope.name);
                console.log("Element deactivated");
            });
        }
    }
});

I'm using it on my links:

<a href="" add-class="class-name">...</a>

But when I click my link my event handlers execute, although scope.name is undefined. I could read attribute value using attributes, but that beats the purpose of assigning attribute values to scope properties as described in Angular Directives API.

What am I doing wrong?

4
  • 1
    better to use a template and ng-click then handle click event directly. Otherwise, you will need to let Angular know (if you want to manipulate the scope) that you are listening to the DOM by calling scope.$apply. Commented Jan 22, 2014 at 17:40
  • 1
    @DavinTryon I don't think $apply() is required here since he's handling the element directly (no digest cycle involved). Besides, his directive seems to be used along with another element, so a custom template couldn't be used. Commented Jan 22, 2014 at 17:47
  • @MichaelBenford: Thanks. You're absolutely correct in what you wrote. Commented Jan 22, 2014 at 17:49
  • @MichaelBenford Yes, that is why I wrote "if you want to manipulate the scope". Commented Jan 22, 2014 at 20:50

2 Answers 2

1

Replace =addClass with @addClass, or, in case you don't need an isolate scope, just read the class name right out of the attribute object:

element.on("click", function() {
    element.addClass(attributes.addClass);
    ...
});

The reason = doesn't work in your case is that it expects a property so a two-way binding can be established and you're providing a static string (I'm assuming you are since class-name isn't a valid property name).

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

5 Comments

It works, but can you please point me to Angular documentation that talks about these? And when you say: ...it expects a property... you're referring to which property? $scope?
@RobertKoritnik Sure. They have moved some parts of the directive's dev guide into the $compile service page. Look for isolateScope.
@RobertKoritnik Yes. If you use =addClass then there should be a property named addClass in the scope the directive is contained.
Well from the Documentation it seems that =addClass should be the value of the element attribute with the same name. It actually shows how you inject it into isolated scope. I'm not too much of Angular Docs fan. I think they lack much info.
@RobertKoritnik I'm truly sorry. My last comment is totally wrong. =addClass means there should be an attribute named add-class containing the name of a property in the parent scope so Angular can bind them together. I have no idea why I said it that way. Be angry at me, not at the Angular documentation. :)
0

try <a href="" add-class="'class-name'">...</a>, note the single-quoted 'class-name'

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.