user776686
user776686

Reputation: 8655

AngularJS: how do I code an element directive with optional attribute parameters?

I'm doing my first steps in AngularJS directives. Just set up this one as an exercise to output a product name:

.directive('productname', function (Prefs) {
        return {
            restrict: 'E',
            replace: true,
            transclude: true,
            templateUrl: '/partials/productname.html',
            link: function (scope, element, attrs) {
                scope.brand = Prefs.owner;
            }
        }
    })

productname.html

<span class="productname"><span class="brand">{{brand}}</span> <span class="product" ng-transclude>{{productname}}</span></span>

and so the usage is plainly: <productname>{{product.name}}</productname>

Now, could someone tell me how I should go about making this directive configurable by adding a flag to output the productname linked?

The usage would be: <productname linked>{{product.name}}</productname> and the output/template would be:

<span class="productname"><a href="/edit/{{id}}"> <span class="brand">{{brand}}</span> <span class="product" ng-transclude>{{productname}}</span></a></span>

Seems complicated and I cannot quite figure out where the logic should be injected...

Upvotes: 3

Views: 8259

Answers (1)

Alp
Alp

Reputation: 29739

First of all, you should use the scope property of the directive declaration. Also, you do not need transclude in this case. Like so:

.directive('productname', function (Prefs) {
    return {
        restrict: 'E',
        scope: {
            product: "=",
            linked: "="
        },
        replace: true,
        templateUrl: '/partials/productname.html',
        link: function (scope, element, attrs) {
            // scope.product and scope.linked are automatically set
            scope.brand = Prefs.owner;
        }
    }
})

And the template:

<span class="productname" ng-switch="linked">
    <a href="/edit/{{id}}" ng-switch-when="true">
        <span class="brand">{{brand}}</span>
        <span class="product">{{product.name}}</span>
    </a>
    <span ng-switch-default>
        <span class="brand">{{brand}}</span>
        <span class="product">{{product.name}}</span>
    </span>
</span>

Call the template like so:

<productname product="product"></productname>

or:

<productname product="product" linked="'true'"></productname>

Update

If you want to use the linked attribute as a flag, you could do that by using the attrs variable:

.directive('productname', function (Prefs) {
    return {
        restrict: 'E',
        scope: {
            product: "="
        },
        replace: true,
        templateUrl: '/partials/productname.html',
        link: function (scope, element, attrs) {
            // scope.product is automatically set
            scope.linked = typeof attrs.linked != 'undefined';
            scope.brand = Prefs.owner;
        }
    }
})

Call it like so:

<productname product="product" linked></productname>

Upvotes: 5

Related Questions