0
votes

I have a directive that wraps a jQuery plugin (cubeportfolio). The plugin renders a basic html images list into a responsive grid.

myDirective:

angular.module('myModule')
    .directive('myDirective', function ($timeout) {
        return {
            restrict: 'A',
            compile: function(tElement, tAttrs) {
                return function (scope, element, attrs) {

                    element.on('$destoy', function() {
                        element.myPlugin('destroy');
                    });

                    $timeout(function() {
                        console.log(attrs);
                        element.myPlugin({
                            myPluginOpt1: attrs.myPluginOpt1,
                            myPluginOpt2: attrs.myPluginOpt2,
                            ...
                        });
                    }, 0, false);
                }
            }
        }
    });


Simplified HTML markup:

<div myDirective myPluginOpt1="opt1">
    <ul>
        <li class="cbp-item">
            <img src="path/to/img1.png">
        </li>
        <li class="cbp-item">
            <img src="path/to/img2.png">
        </li>
    </ul>
</div>


To have the <ul> tag filled with data from API call, I used the ng-repeat directive build the list.

<div myDirective myPluginOpt1="opt1">
    <ul>
        <li class="cbp-item" ng-repeat="item in items">
            <img src="path/to/imgX.png">
        </li>
    </ul>
</div>


But unfortunately the jQuery plugin is called before Angular processes inner ng-repeat directive, so only the first item is rendered. How to make sure the jQuery plugin in myDirective is called after all inner HTML has been processed?

I know I can write another custom directive which handles the $last event of ng-repeat and sends it to the parent but I want myDirective completely independant from its HTML content.

1

1 Answers

0
votes

Instead of using the compile function which is called only once and before any binding occurs, you better use the link function which is called every time the element is to be bound to data in the $scope object. You will also need to add a $watch to the scope object that represents the list. Perhaps something like this (not tested):

angular.module('myModule')
     .directive('myDirective', function ($timeout) {
        return {
            restrict: 'A',
            scope: {
                items: '='
            },
            link: function(scope, element, attrs) {
                scope.$watch('items', function(newValue) {
                   if (newValue && newValue.length>0) {
                       element.myPlugin({
                            myPluginOpt1: attrs.myPluginOpt1,
                            myPluginOpt2: attrs.myPluginOpt2,
                            ...
                        });
                   }
                })
            }
        }
    });

The watch listens to changes in the list, the idea is here is to enable the plugin only when the list has elements. Let me know if it works!

Regards, Daniel