mhartington
mhartington

Reputation: 7025

Custom Angular Directive not working with dynamic images

I'm working on a custom directive for AngularJs that has a image rotator based on a Jquery Plugin I wrote, which can be seen here

Here is my directive

.directive('imageRotator', function () {
    return {
        restrict: 'A',
        link: function ($scope, $element, $attr) {
            console.log('Before Function');
            $element.j360();
            console.log('After Function');
        }
    };
});

Now the directive works when I hard code the series of images as in the demo, but when I try to make the images dynamic by combining and ng-repeat, the plugin does not work. I read here about using $compile when using dynamic html which like this:

<div class="product" image-Rotator>
    <img ng-repeat="img in page.imgs" class="child" ng-src="img/{{product.sku}}/{{img}}.png">
</div>

But when I use $compile, I get errors in my console:

TypeError: undefined is not a function
    at link (http://0.0.0.0:8000/js/controllers.js:48:14)
    at nodeLinkFn (http://0.0.0.0:8000/js/angular/angular.js:6220:13)
    at compositeLinkFn (http://0.0.0.0:8000/js/angular/angular.js:5630:15)
    at compositeLinkFn (http://0.0.0.0:8000/js/angular/angular.js:5633:13)
    at publicLinkFn (http://0.0.0.0:8000/js/angular/angular.js:5535:30)
    at boundTranscludeFn (http://0.0.0.0:8000/js/angular/angular.js:5649:21)
    at controllersBoundTransclude [as $transclude] (http://0.0.0.0:8000/js/angular/angular.js:6241:18)
    at ngDirective.link (http://0.0.0.0:8000/js/angular/angular.js:19898:16)
    at nodeLinkFn (http://0.0.0.0:8000/js/angular/angular.js:6220:13)
    at compositeLinkFn (http://0.0.0.0:8000/js/angular/angular.js:5630:15) <div class="product" image-rotator=""> 

This maybe a bit over my head as my knowledge of angular isn't great so I'm not sure what the correct way is to make a directive especially with dynamic data.

Any ideas on what I need to do to get this to work with dynamic images? Any help or ideas are appreciated.

Heres a plunker with the directive.

Upvotes: 1

Views: 502

Answers (1)

Danny
Danny

Reputation: 7518

So your plunker had two problems. I'll start with the simple one

<img ng-repeat="img in imgs" class="child" ng-src="'{{src}}'">

You are iterating over imgs and storing that image object in img, because of so your code should look like the following instead.

<img ng-repeat="img in imgs" class="child" ng-src="{{img.src}}">

Notice the img.src. Next was the slightly more confusing issue, you needed to call your jQuery plugin only after AngularJS had created the DOM from the ng-repeat. From a couple of google searches and this answer, it seemed that the best way of doing so was to put your plugin call inside of $timeout.

.directive('imageRotator', function ($timeout) {
  return {
      restrict: 'A',
      link: function ($scope, $element, $attr) {
          console.log('Before Function');
          $timeout(function() {
            $element.j360();
          });

          console.log('After Function');

      }
  };
});

I don't know much about AngularJS, but from what I could gather the $digest cycle is responsible for creating the DOM, and using $timeout with no delay will wait for the $digest cycle to finish and then execute your function. I may be wrong about this, but it worked for me.

Upvotes: 1

Related Questions