Mike Bryant
Mike Bryant

Reputation: 2475

Pass scope and parameters to directive - AngularJS

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>

Upvotes: 1

Views: 326

Answers (2)

Tong Shen
Tong Shen

Reputation: 1367

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.

Upvotes: 1

Mike Bryant
Mike Bryant

Reputation: 2475

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;

                }

            }
        };
    });

Upvotes: 1

Related Questions