1

I'm trying to set a class in a ng-repeat with a directive.

I need to pass a parameter to this directive: wineQty

if I use scope: { wineQty: '=' } this works however $scope.bullet1Color is undefined in my html and thus doesn't affect the class that I want.

If I use scope: '@' I get the correct class however I can't specify wineQty

Is there a way to combine theses two syntaxes? so that I can access the scope and pass a paramater?

I've tried { wineQty: '@' } but with no luck sadly.

Here's my directive

angular.module('myApp').directive('wineQtyBullets', function () {
        return {
            restrict: 'A',
            scope: { wineQty: '=', totalBullets: '=', numRedBullets: '=', numOrangeBullets: '@', bullet1Color: '@' },
            link: function (scope, element, attrs) {
                // defaults
                var defaultNumRedBullets = 1;
                var defaultNumOrangeBullets = 2;
                var defaultTotalBullets = 12;
                var defaultWineQty = 0;

                // set values from attributes
                var numRedBullets = scope.numRedBullets ? scope.numRedBullets : defaultNumRedBullets;
                var numOrangeBullets = scope.numOrangeBullets ? scope.numOrangeBullets : defaultNumOrangeBullets;
                var totalBullets = scope.totalBullets ? scope.totalBullets : defaultTotalBullets;
                var wineQty = scope.wineQty ? scope.wineQty : defaultWineQty;


                for (var currentBullet = 1; currentBullet <= totalBullets; currentBullet++) {

                    var bulletColorClass = 'bg-grey';

                    if (currentBullet <= wineQty) {
                        if (currentBullet <= numRedBullets) {
                            bulletColorClass = 'bg-red';
                        }
                        else if (currentBullet <= (numOrangeBullets + numRedBullets)) {
                            bulletColorClass = 'bg-orange';
                        }
                        else {
                            bulletColorClass = 'bg-green';
                        }
                    }


                    scope["bullet" + currentBullet + "Color"] = bulletColorClass;

                }
                console.log(scope.bullet1Color);

            }
        };
    }
);

Here's my html

<div class="bullets pull-left ml15 mt6" wine-qty="wine.owned_qty" wine-qty-bullets>
            <ul>
                <li class="bullet"
                    ng-class="bullet1Color"></li>
</ul>
</div>
1

2 Answers 2

1

I managed to solve the problem, by changing scope to true and accessing the parameters through attrs

If this can help anyone here's the directive:

angular.module('myApp').directive('wineQtyBullets', function () {
        return {
            restrict: 'A',
            scope: true,
            link: function (scope, element, attrs) {

                var options = { };
                angular.forEach([
                    'numRedBullets',
                    'numOrangeBullets',
                    'totalBullets',
                    'wineQty'
                ], function (key) {
                    if (angular.isDefined(attrs[key]))
                        options[key] = attrs[key];
                });

                // defaults
                var defaultNumRedBullets = 1;
                var defaultNumOrangeBullets = 1;
                var defaultTotalBullets = 12;
                var defaultWineQty = 0;


                // set values from attributes
                var numRedBullets = parseInt(options.numRedBullets) ? parseInt(options.numRedBullets) : defaultNumRedBullets;
                var numOrangeBullets = parseInt(options.numOrangeBullets) ? parseInt(options.numOrangeBullets) : defaultNumOrangeBullets;
                var totalBullets = parseInt(options.totalBullets) ? parseInt(options.totalBullets) : defaultTotalBullets;
                var wineQty = parseInt(options.wineQty) ? parseInt(options.wineQty) : defaultWineQty;


                for (var currentBullet = 1; currentBullet <= totalBullets; currentBullet++) {

                    var bulletColorClass = 'bg-grey';

                    if (currentBullet <= wineQty) {
                        if (wineQty <= numRedBullets) {
                            bulletColorClass = 'bg-red';
                        }
                        else if (wineQty <= (numOrangeBullets + numRedBullets)) {
                            bulletColorClass = 'bg-orange';
                        }
                        else {
                            bulletColorClass = 'bg-green';
                        }
                    }


                    scope["bullet" + currentBullet + "Color"] = bulletColorClass;

                }

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

1 Comment

You should accept your answer as correct to help others :)
1

Using "=" means 2-way data binding, and it's definitely fine.

The problem might be that your link function are executed only once at the very beginning, when it's possible that the values of your attributes are not yet assigned (may be caused by some AJAX calls).

I would suggest that you wrap all your link function into a scope.$watch function. Like:

        link: function (scope, element, attrs) {
            scope.$watch(function() {
                return { 
                    wineQty: scope.wineQty, 
                    totalBullets: scope.totalBullets, 
                    numRedBullets: scope.numRedBullets, 
                    numOrangeBullets: scope.numOrangeBullets, 
                    bullet1Color: scope.bullet1Color 
                }
            }, function() {
                // Your original code here.
            })
        }

Then your final result will automatically update if your directive got new attribute values.

1 Comment

Thanks, this didn't work for me but saved me alot of time nonetheless, I had never used scope.$watch and helped me refresh certain parts of my view. Regarding the question that I asked in this thread I managed to achieve what I wanted, I posted my answer above.

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.