简体   繁体   中英

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>

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;

                }

            }
        };
    });

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM