13

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.

be-codified
  • 5,704
  • 18
  • 41
  • 65
  • Just create a scope variable to check this out. Theres no need to pass as string. You should pass as variable – Fals Jun 22 '15 at 16:46

4 Answers4

13

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);
        }
    }
})
Dmitri Algazin
  • 3,332
  • 27
  • 30
10

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.

ryanm
  • 2,239
  • 21
  • 31
  • 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. – sean2078 Feb 19 '18 at 07:36
  • @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? – ryanm Feb 20 '18 at 14:43
  • @sean2078 You just need use [`ng-attr-`](https://stackoverflow.com/questions/22049824/conditionally-adding-data-attribute-in-angular-directive-template) with this one. – tsh Sep 11 '18 at 09:12
  • 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! – Aspiring Dev Apr 18 '21 at 19:49
9

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.

Community
  • 1
  • 1
Josh Beam
  • 19,292
  • 3
  • 45
  • 68
  • @JBNizet, yeah I just realized that, I changed my answer right before you commented (it now says `var requiredParam == attrs.requiredParam === 'true'`. – Josh Beam Jun 22 '15 at 16:45
  • 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. – be-codified Jun 22 '15 at 16:57
  • 1
    @Zigson, I would suggest reading the AngularJS docs for directives, it provides pretty good explanation for how to use link. – Josh Beam Jun 22 '15 at 17:01
1

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

random_user_name
  • 25,694
  • 7
  • 76
  • 115
Lalit Sachdeva
  • 6,469
  • 2
  • 19
  • 25
  • 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 Jun 23 '15 at 11:54
  • This is working, I have forgot to bind requiredParam (put them in curly brackets). – be-codified Jun 23 '15 at 22:27