AngularJS: passing boolean value to directive

27,540

Solution 1

HTML

<city-zip city="clientCity" zip="clientZip" required-param="true"></city-zip>
<city-zip city="clientCity" zip="clientZip" required-param="{{ someBooleanValue }}"></city-zip>

Angular

.directive('cityZip', function() {
    return {
        restrict: 'E',
        templateUrl: '../templates/templateCityZip.html',
        scope: {
            city: '=',
            zip: '=',
            requiredParam:'@'
        },
        link: function(scope) {
            console.log("requiredParam", scope.requiredParam);
        }
    }
})

Solution 2

I think the simplest / cleanest answer has not yet been included for this question. This answer also fits within the HTML5 Spec for a boolean attribute - http://www.w3.org/TR/html5/infrastructure.html#boolean-attributes

2.5.2 Boolean attributes

A number of attributes are boolean attributes. The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.

If the attribute is present, its value must either be the empty string or a value that is an ASCII case-insensitive match for the attribute's canonical name, with no leading or trailing whitespace.

The values "true" and "false" are not allowed on boolean attributes. To represent a false value, the attribute has to be omitted altogether.

HTML:

<city-zip city="clientCity" zip="clientZip" requiredParam></city-zip>

And the directive:

.directive('cityZip', function() {
    return {
        restrict: 'E',
        templateUrl: '../templates/templateCityZip.html',
        scope: {
            city: '=',
            zip: '='
        },
        controller: function($scope, $attrs) {
            $scope.requiredParamExists = $attrs.hasOwnProperty( 'requiredParam' );
        }
    }
});

Simple, fits cleanly with HTML5 spec for boolean attributes, and no need to coerce a string to a scope variable ('requiredParam': '=').

Note in the example code above, if minified, the required variables $scope and $attrs will change to a shorter string and break the code, but that's another issue.

Solution 3

Inside link, you can access the attribute:

return {
    // code
    link: link
}

function link(scope, $el, attrs) {
    var requiredParam = attrs.requiredParam === 'true';
}

That'll coerce the string value to a boolean (if the string value is 'true', it'll return true, otherwise it'll return false.)

The main part here is how to convert a string value "true" or "false" to its boolean form, since !!'true' and !!'false' both return true. See this answer for the solution and extended discussion.

If you need to use the value in your controller, you can do the same pattern in the scope object and pass it in its coerced form to the coupled controller.

Solution 4

There are 3 parameters that you can pass in the link function which work on the directive. Parameters are scope, element and attributes.

  1. scope gives the scope of the controller that directive is put under.

  2. element passes the information about the DOM element on which it is applied

  3. attributes passes the information about all DOM element attributes that are on the element.

    <city-zip ng-app="myapp" city="clientCity" zip="clientZip" required-param="true"></city-zip>
    
    angular.module("myapp", []).directive('cityZip', function() {
    return {
        restrict: 'E',
        templateUrl: '',
        scope: {
            requiredParam:'@'
        },
        link: function(scope, $el, attrs) {
            alert( attrs.requiredParam);
        }
    }
    

    })

Working jsFiddle

Share:
27,540
be-codified
Author by

be-codified

Hi, my name is Žiga and I'm a front-end web developer.

Updated on July 09, 2022

Comments

  • be-codified
    be-codified almost 2 years

    I can not pass boolean value to my directive.

    Here is my HMTL:

    <city-zip city="clientCity" zip="clientZip" requiredParam="'true'"></city-zip>
    

    And directive:

    .directive('cityZip', function() {
        return {
            restrict: 'E',
            templateUrl: '../templates/templateCityZip.html',
            scope: {
                city: '=',
                zip: '='
            },
            controller: function($scope) {}
        }
    });
    

    Any help would be much appreciated.

  • Josh Beam
    Josh Beam about 9 years
    @JBNizet, yeah I just realized that, I changed my answer right before you commented (it now says var requiredParam == attrs.requiredParam === 'true'.
  • be-codified
    be-codified about 9 years
    Thank you for your answer. My directive is not working, possible because link and controller at the same time? Can you point me how to do this in controller? I even don't know why link is for.
  • Josh Beam
    Josh Beam about 9 years
    @Zigson, I would suggest reading the AngularJS docs for directives, it provides pretty good explanation for how to use link.
  • be-codified
    be-codified about 9 years
    I am sorry, this returns undefined.
  • Dmitri Algazin
    Dmitri Algazin about 9 years
    check now, edited 'required-param=', was 'requiredParam='
  • be-codified
    be-codified about 9 years
    Thank you for your effort. I do get true or false but somehow I think this is not really boolean. I am using ng-required="requiredParam" in my directive template: I get validation errors although ng-required is set to true.
  • be-codified
    be-codified about 9 years
    I have changed this. Can you please take a look at my bottom comment about ng-required?
  • be-codified
    be-codified about 9 years
    This is working, I have forgot to bind requiredParam (put them in curly brackets).
  • silencedmessage
    silencedmessage about 8 years
    @DmitriAlgazin's comment saved me. I keep forgetting in Angular they take the camelCaseNames and make them all-weird-like.
  • sethreidnz
    sethreidnz about 8 years
    @silencedmessage AKA 'snake case'
  • sean2078
    sean2078 over 6 years
    Big problem with this implementation is if you want to use a component with this type of attribute template inside your own component and, at the same time, dynamically include or not include that attribute. For example, if you wanted to turn off or on ui-select's "multiple" attribute dynamically w/o repeating the HTML element and using ng-if. Based on this alone I personally recommend to never use the pattern in this answer.
  • ryanm
    ryanm over 6 years
    @sean2078 I'm not quite tracking, as it has been a while since I worked on this issue. Can you give an example of the problem and/or what you found to work better, for posterity?
  • tsh
    tsh almost 6 years
    @sean2078 You just need use ng-attr- with this one.
  • Aspiring Dev
    Aspiring Dev about 3 years
    I ended up going with this approach. Simpler than all the other stuff I saw plus the directive I'm working on is not implemented using isolated scope. Isolated scope seemed to break it so this is it. Thank you!