3

I'm trying to get the lightGallery jQuery plugin (http://sachinchoolur.github.io/lightGallery/index.html) to work with AngularJS.

I found some answers that suggested I needed a directive, so I created the following:

.directive('lightGallery', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            jQuery(element).lightGallery();
        }
    };
})

Then in my view I do this:

<ul lightGallery>
    <li ng-repeat="photo in album.photos" data-src="{{photo.fullres}}">
        <img ng-src="{{photo.thumbnail}}" />
    </li>
</ul>

(I also tried with <ul light-gallery>) When I run the page nothing happens when I click any of the thumbnails. I can put an alert() in the link function, though, and that is displayed.

How can I get AngularJS to play along with jQuery and this plugin?

UPDATE:

After some debugging it seems that jQuery(element).lightGallery() is executed before the model is bound to the view. So the question then is how I can get a directive to be called when everything is bound and not before.

1
  • 1
    How do you load lightGallery into AngularJS project? Commented Feb 4, 2017 at 14:29

3 Answers 3

11

Call lightGallery once ng-repeat is finished rendering.
You can just modify the directive like this

.directive('lightgallery', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      if (scope.$last) {

        // ng-repeat is completed
        element.parent().lightGallery();
      }
    }
  };
});

HTML

<ul>
  <li lightgallery ng-repeat="photo in photos" data-src="{{photo.fullres}}">
    <img ng-src="{{photo.thumbnail}}" />
  </li>
</ul>

Here is the demo plnkr

Sign up to request clarification or add additional context in comments.

4 Comments

A follow up question. lightGallery documentation states that you can use the data-sub-html attribute to display captions for images. I added this attribute to the LI element, but nothing was displayed. I also tried adding a separate div (inside the LI) and referring to that instead, but that didn't work either. Any tips on how to use the captions when using AngularJS?
Caption works fine for me. I think your caption div doesn't have any style so it is hiding behind the image. Either you can use lightGallery default '.custom-html' class or you can apply css by yourself. here is the updated plnkr
Ah, I was missing the .custom-html class. If I encapsulated my caption in a div with that class the captions works. The documentation might need updating as that says <li data-sub-html="<h3>My caption</h3><p>My description..</p>" /> </li> which is exactly what I had.
uh, isn't that instantiating multiple lightgallery widgets for each item?
1

without directive..

HTML

<ul id="lightgallery">
  <li ng-repeat="image in album.images" data-src="{{imagem.fullres}}">
    <img ng-src="{{image.thumbnail}}" />
  </li>
</ul>

JavaScript

// $http, Restangular whatever to return data in album.images

// unbind before..
jQuery('#lightgallery').unbind().removeData();

// $timeout after
$timeout(function () {
  jQuery('#lightgallery').lightGallery();
}, 100);

Works for me..

3 Comments

Maybe number 100 was sufficient for you. For sure this is highly unreliable
No. It has worked perfectly for 2 years on a large-scale project that uses this feature. : )
somehow only this solution solved my problem, maybe there could be other ways to do it. Perhaps instead of doing removeData there shall be a way to destroy instances of lightgallery. Better approach would be wrapping it inside angularjs directive.
0

Using a combination of 2 directives allows you to specify a parent via a directive, as well as pass in options to a scoped variable, which provides the opportunity for more customization of Light Gallery. The secondary directive triggers the parent to bind (using the same idea presented in @Clr's solution)

This directive is for the parent element, and you may pass a galleryOptions scope variable which is simply passed along when binding Light Gallery:

.directive('lightGallery', function() {
    return {
        restrict: 'A',
        scope: {
            galleryOptions: '='
        },
        controller: function($scope) {

            this.initGallery = function() {
                $scope.elem.lightGallery($scope.galleryOptions);
            };

        },
        link: function(scope, element, attr) {
            scope.elem = element;
        }
    }
})

This directive is for each "item" in the Light Gallery:

.directive('lightGalleryItem', function() {
    return {
        restrict: 'A',
        require: '^lightGallery',
        link: function (scope, element, attrs, ctrl) {

            if (scope.$last) {
                ctrl.initGallery();
            }

        }
    }
})

The resulting markup (which can really be anything you'd like by specifying the selector option when initializing Light Gallery):

<ul light-gallery gallery-options="galleryOptions">
    <li ng-repeat="photo in album.photos" data-src="{{photo.fullres}}" light-gallery-item>
        <img ng-src="{{photo.thumbnail}}" />
    </li>
</ul>

Whereas options may be any valid Light Gallery options, such as:

$scope.galleryOptions = {
    selector: '.file-trigger',
    ...
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.