最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Trying to convert jquery plugin to Angular Directive - Stack Overflow

programmeradmin4浏览0评论

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 .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());
  } 
}
});
  • I wanted to clean up my html, so used a class (restrict C?) - set the barcode value within the scope.

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...

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./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());
  } 
}
});
  • I wanted to clean up my html, so used a class (restrict C?) - set the barcode value within the scope.

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...

Share Improve this question edited Oct 2, 2013 at 0:37 Rob asked Oct 1, 2013 at 23:32 RobRob 1,6363 gold badges25 silver badges54 bronze badges 8
  • Split is part of the String Object in javascript. If 9002236311036 is an integer, it will not have access to the split method. Maybe try turning it into a string first? – francisco.preller Commented Oct 2, 2013 at 0:03
  • Thanks - that works :) I added toString on the end and it functions well. I still don't know why it works though... – Rob Commented Oct 2, 2013 at 0:22
  • Glad it helped! Do you mean you don't understand how directives work? – francisco.preller Commented Oct 2, 2013 at 0:22
  • yep - I see lots of different ways of implementing them. Mostly examples without any explanation. I read that they're a way to extend html... but I still don't quite get why you'd want to do that as well? – Rob Commented Oct 2, 2013 at 0:25
  • Let me post an answer for this since it'll be a little more lengthy than a ment will allow... – francisco.preller Commented Oct 2, 2013 at 0:27
 |  Show 3 more ments

4 Answers 4

Reset to default 7

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 bee 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 = ment
        restrict: 'A',
        // The directive piler 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 piler 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());
        }
    };
});

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 bees 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.

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?

Using this library for the barcode: https://github./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

发布评论

评论列表(0)

  1. 暂无评论