1

I have a custom angular directive that graphically represents an “activity” in my webapp. I use it like this:

<activity-box ng-repeat="act in activities"
    model="act" active="{{currentActivity == act}}" />

My directive has an isolated scope and declares model and active like this:

appDirectives.directive('activityBox', function() {
    return {
        template: '<div ng-class="{activityActive: active == \'true\'}">{{model.name}}</div>',
        restrict: 'E',
        replace: true,
        scope: {
            model: '=',
            active: '@'
        },
        link: ...
    };
});

I have no worry about the model attribute, but my active attribute is always treated as a string. When currentActivity == act is true, then active holds the string value "true" (and not the boolean true), or else, "false" (and not false).

This means that although it conceptually is a boolean, I must treat it as a string. For instance, I'd like to write ng-class="{activityActive: active}" instead ng-class="{activityActive: active == 'true'}". Right now, if I forget the extra part, this always evaluate to true, as both "false" and "true" are truthy.

Is there any way for me to obtain non-string attributes like this? What's the best way to achieve this?

2
  • 2
    When you pass the argument with @ it is always treated as a string (in your case it is interpolated first though). If you want the value of an expression you should go with =. PLNKR that demonstrates it. Commented May 16, 2014 at 13:43
  • @arturgrzesiak Thanks a lot — I hadn't realised I could also use full expressions (even non-assignable ones) in an attribute mapped with '='. Commented May 16, 2014 at 14:13

2 Answers 2

1

What about?

<activity-box ng-repeat="act in activities"
    model="act" active="currentActivity == act" />

scope: {
            model: '=',
            active: '='
        },

Just tried - it works. And has binding, so if 'currentActivity' or 'act' would change, value of 'active' inside directive would also change.

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

1 Comment

Thanks a lot — for debugging purposes, I had bound active to an <input type="checkbox" ng-model="active"> in my template, and this was (understandably) throwing a noassign exception when I clicked the checkbox. I though this was thrown at compile time and had given up on that solution. Thanks a lot!
1

As the code is shown above the directive is not associated to your tag.

By default directives are restricted to attributes only, and you are attempting to use it as an element.

In your directive add this line:

replace: true,
restrict: 'E', // <--- This line
scope: {

EDIT You can accept in the active flag by linking it to the parent scope using = when defining your scope, but changing it in your directive changes it in your controller's scope

active="currentActivity == act"
scope: { active: '=' }

But you can accept it via a string and parse it in your controller using the $parse service:

active="{{currentActivity == act}}"
scope: { active: '@' }
link: function(scope){
    var booleanValue = $parse(scope.active)();
}

9 Comments

Actually I did have restrict: 'E' in my code, but accidentally omitted it in my question when I copy-pasted. Your answer does not address the string-vs-boolean problem.
You are correct, but what you had above is a workable solution even though you desired a different means of getting there. I tried to explain different ways you can reference the parent scope in your directive in my updated answer, hopefully that clarifies the differences between = and @
If I use $parse, though, it means booleanValue won't be automatically updated when the model changes, right? I'd have to $watch the attribute.
You are correct, except you'd have to use & which allows you to just look into the referencing controller's scope. see this example: plnkr.co/edit/ae9QlfM1aT8929fiaOPr?p=preview
Yes, while the directive's scope is a child of the controller's scope it would make the directive tired to a specific implementation in the controller. This would also impact the testability of the directive.
|

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.