Magnific Popup & AngularJS

Alexandra Ackerman
2 min readFeb 6, 2015

--

jQuery Plugins and Angular’s NG-Repeat (Dynamically Generated DOM Elements)

If you’ve ever used jQuery plugins with AngularJS, you may have run into a few issues with grabbing a hold of dynamically generated DOM elements. This is a simple guide to explain how I solved this problem using Macnific Popup in a ng-repeat based gallery of images.

The Problem

Magnific Popup is a responsive lightbox and dialog script that works with jQuery. I wanted to use this plugin to display a gallery of images on my Angular app, but I couldn’t get Magnific to initialize because the function is supposed to be called after document ready. Here’s how their documentation explains initializing.

$(document).ready(function() {
$('.image-link').magnificPopup({type:'image'});
});

Seems easy enough, but because Angular generates DOM elements dynamically, I couldn’t get Magnific to find my images.

To make things a little clearer, imagine that I have a group of images in scope that I want to display with ng-repeat.

$scope.images = [
{src: http://placekitten.com/g/200/300, title: 'Cute kitten'},
{src:
http://placekitten.com/g/300/300, title: 'Cuter kitten'},
{src:
http://placekitten.com/g/400/400, title: 'Cutest kitten'}
]
<div class="gallery">
<div ng-repeat="image in images">
<a href="{{image.src}}" class="image" title="{{image.title}}">
<img src="{{image.src}}">
</a>
</div>
</div>

Initially, I tried calling the initialize function as soon as my controller loaded. The problem was, though my data was loading, the ng-repeated DOM elements weren’t, so Magnific popup was completely ineffective.

The Solution

To solve this problem, I added a $watch inside of my controller to keep an eye on the items I wanted to use in my ng-repeat. In addition to that, I added a $timeout inside of the function so that the initializer would run after Angular manipulated the DOM and rendered the repeated elements in the browser. Viola! Then I called my Magnific popup initialization.

$scope.$watch("images", function (newValue, oldValue) {
$timeout(function() {
$('.gallery').each(function() {
$(this).magnificPopup({
delegate: '.image',
type:'image',
gallery: {
enabled: true
},
titleSrc: function(item){
return item.el.attr('title');
}
});
});
});
});

Put simply, this $watch function calls Magnific’s initialize function after the DOM is rendered from ng-repeat, rather than on document ready. Calling the initialize function like this allows Magnific popup to work just as you would expect it to, generating a clean lightbox gallery from your images.

While this may not be the most elegant solution to the dynamically generated DOM elements and jQuery plugin problem, it offers a simple workaround that gets the job done.

If you have any questions, feedback or would like to offer an even better solution to the problem, feel free to reach out to me on Twitter or leave comments.

Thanks for reading!

--

--

Alexandra Ackerman

Alexandra is Developer @Contently and lecturer @TheNewSchool. Loves journalism & coding