Rob
Rob

Reputation: 1636

Trying to convert jquery plugin to Angular Directive

Within a loop, I have:

<div class="barcode" class="thumbnail"> 
  <canvas class="ean" barcode-generator barcode-value="9002236311036"> </canvas>
</div>

Which loops out a load of barcodes. I've statically added the barcode-value, but the intention is for this to be added via {{barcodeNumber}}

I've found a really nice plugin https://github.com/joushx/jQuery.EAN13 which converts a number to a barcode.

Following various tutorials, I've written the following Directive (although I don't quite get the HOW or WHY as yet). I've also included jquery above Angular, and the plugin after Angular.

app.directive('barcodeGenerator', function () {
return {
  restrict: 'A',
  scope: {
    barcodeValue: '='
  },
  link: function (scope, elem, attrs) {
    console.log("Recognized the barcode directive usage");
    $('.ean').EAN13(scope.barcodeValue);
  }
}
});

The console.log works - but then the bit where I call the plugin doesn't... Chrome debug displays the following error:

TypeError: Object 9002236311036 has no method 'split'

I'm not sure what I'm doing wrong - have read lots of forum posts, but can't quite grok it.

Thanks, Rob

Edit - following on from Francisco's post below - adding toString() has worked. Only thing is, I don't know why / how this is working.

app.directive('barcodeGenerator', function () {
return {
  restrict: 'A',
  scope: {
    barcodeValue: '='
  },
  link: function (scope, elem, attrs) {
    console.log("Recognized the barcode directive usage");
    $('.ean').EAN13(scope.barcodeValue.toString());
  }
}
});

So I've done a little refactoring:

app.directive('ean', function () {
return {
  restrict: 'C',
  scope: {
    barcodeValue: '='
  },
  link: function (scope, elem) {
    console.log("Recognized the barcode directive usage");
    $(elem).EAN13(scope.barcodeValue.toString());
  } 
}
});

Then in my html, I added:

<div class="barcode" class="thumbnail"> 
  <canvas class="ean" barcode-value="{{barcode}}"> </canvas>
</div>

And this is where it errors... the barcode-value. Before it was hardwired and worked... now I try to put it in the loop, it doesn't.

Edit...

<div class="barcode" class="thumbnail"> 
  <canvas class="ean" barcode-value="barcode"> </canvas>
</div>

Removing the curly brackets worked.... hmm... I need to get a manual...

Upvotes: 1

Views: 3077

Answers (4)

Rob
Rob

Reputation: 1636

Using this library for the barcode: https://github.com/joushx/jQuery.EAN13

app.directive('ean', function () {
return {
  restrict: 'C',
  scope: {
    barcodeValue: '='
  },
  link: function (scope, elem, attr) {
    console.log("Recognized the barcode directive usage");
    $(elem).EAN13(scope.barcodeValue.toString());
  }
}
});

and

<div class="barcode" class="thumbnail" ng-show="voucher.barcode">
<canvas class="ean" barcode-value="voucher.redemptionCode"> </canvas>
</div>

and if I recall correctly - any number you pump in gets converted to the barcode (although its been over a year since I did this... )

Hope this helps

Upvotes: 0

user3404455
user3404455

Reputation: 440

Trying to get something similar to work with no success..the barcode will just not display..do you have all your code on github to use?

Upvotes: 1

Cool Java guy מוחמד
Cool Java guy מוחמד

Reputation: 1727

The francisco.preller is absolutely right. Just one improvement is required. If you change

link: function (scope, elem, attrs) {
        console.log("Recognized the barcode directive usage");
        $('.ean').EAN13(scope.barcodeValue.toString());
    }

with

link: function (scope, elem, attrs) {
        console.log("Recognized the barcode directive usage");
        elem.EAN13(scope.barcodeValue.toString());
    }

Not only it becomes more angularized, but it also follows the role of the 'elem' parameter, which is already a jQuery object (or jQLite, which is a jQuery subset, if jQuery is not loaded). Any use of direct DOM manipulation is said to be a bad practice by Google, as it could not always be reflected in Angular's digest cycle and will cause unexpected behavior.

Upvotes: 2

francisco.preller
francisco.preller

Reputation: 6629

Directives are a way to extend HTML. The whole purpose behind doing this is that AngularJS encourages to keep all DOM manipulation outside of controllers so they become testable.

I won't get into detail of how exactly directives work, it's possibly both the most powerful and most confusing aspect of AngularJS.

In short though, referring to what you've done:

app.directive('barcodeGenerator', function () {
    return {
        // Restrict tells AngularJS how you will be declaring your directive in the markup.
        // A = attribute, C = class, E = element and M = comment
        restrict: 'A',
        // The directive compiler actually happens before the $scope is available in AngularJS, therefore
        // You need to pass certain values into your scope. In this instance, you are passing the barcodeValue
        // attribute and telling it its equal. In other words where you use scope.barcodeValue.toString() below
        // You are able to do this because of the below declaration. There are other symbols you can use to tell
        // the compiler to do other things such as interpret the values as a method, but I'll let you investigate
        scope: {
            barcodeValue: '='
        },
        // The link function passes the element to the directive and allows you to manipulate the dom
        // You could event try to replace $(.ean) with just elem below, since you are passing the scope,
        // element and attribute to the function below, then using the jQuery plugin to do the rest.
        link: function (scope, elem, attrs) {
            console.log("Recognized the barcode directive usage");
            $('.ean').EAN13(scope.barcodeValue.toString());
        }
    };
});

Upvotes: 7

Related Questions