3

I'm using an Angular element directive to generate an amount of stars (rating) for a given item.

I create a directive called 'generateStars' and I am using it like so in the view.

<generate-stars amount="3"></generate-stars>

I don't want the directive to be dependant on the current scope so I was wondering if I could take in the "amount" attribute and get the value within my directive function.

Here is that function:

angular.module('myapp.directives', [])

.directive('generateStars', function() {
    var html = '<i class="fa fa-star"></i>';

    return {
        restrict: 'E',
        template: html,
        replace: true
    };
});

I couldn't find any obvious documentation to allow me to get the value of 'amount' inside my directive function.

Any help would be much appreciated. Thanks.

3 Answers 3

3

You could use isolated scope and use amount value can be passed as attribute as you are doing so.

Markup

<generate-stars amount="{{amount}}"></generate-stars>

Controller

$scope.amount = 3; //passing it through the scope.

Directive

angular.module('myapp.directives', [])

.directive('generateStars', function() {
    var html = '<i ng-repeat="i in [1, 2, 3, 4, 5]" class="fa fa-star" ng-if="i>=amount"></i>';

    return {
        restrict: 'E',
        template: html,
        replace: true,
        scope: { 
           amount: '@' //`@` for one way binding.
        }
    };
});

This can be without isolated scope. Basically you need to create class fa-3x in your directive template.

angular.module('myapp.directives', [])

.directive('generateStars', function() {
        return '<i ng-repeat="i in [1, 2, 3, 4, 5]" class="fa fa-star" ng-if="i>='+ attrs.amount +' "></i>'
    };

    return {
        restrict: 'E',
        template: html,
        replace: true
    };
});
Sign up to request clarification or add additional context in comments.

3 Comments

fa-3x is for font-size, not for amount of icons.
Thanks for your reply. This code sample doesn't allow me to take in the value given from the HTML element and use it within my directive. I would like to avoid using 'scope' altogether. I just want to take the value in from the HTML attribute in the custom directive element.
@Dan did you tried the second example which I;ve added in answer..it plays with attribute only..without considering scope
1

You can use attrs object available in your link function of your Directive Definition Object.

angular.module('myapp.directives', [])
.directive('generateStars', function() {
    var html = '<i class="fa fa-star"></i>';

    return {
        restrict: 'E',
        template: html,
        replace: true,
        link: function(scope, element, attrs) {
           /*all attributes passed to directive are available as properties
              on attrs object*/
            console.log(attrs.amount);
        }
    };
});

HTML

<generate-stars amount="3"></generate-stars>

With that, when your directive is rendered, prints the value 3 in console.

2 Comments

I'm trying to use the "amount" variable inside the directive before the return statement. In this case I need to know that the amount is equal to 3 and then generate 3 HTML elements to return.
I think you're confused by the return statement. You're basically returning a definition object while registering your custom directive with angular. It's link function is called before translating your custom directive code to your html (referred by template) in the browser
0

I appreciate the help guys but neither of these solutions ended up working out for me. This is what I ended up doing.

angular.module('myApp.directives', [])

.directive('generateStars', function() {
    var html = '<i class="fa fa-star" ng-repeat="n in [] | range:roundedAmount"></i>';

    return {
        restrict: 'E',
        scope: {
            amount: '='
        },
        link: function(scope, element, attrs) {
            scope.roundedAmount = parseInt(scope.amount);
        },
        replace: true,
        template: html
    };
})

.filter('range', function() {
    return function(input, total) {
        total = parseInt(total);
        for (var i=0; i<total; i++)
            input.push(i);

        return input;
    };
});

Comments

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.