Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

I'm trying to create my own image carousel as an angularjs directive; I want to keep it as lightweight and unopinionated as possibile, so I thought I'd just create a <carousel></carousel> wrapper for a set of <img> elements, like so:

<carousel>
   <img ng-repeat="image in images" ng-src="{{image.src}}" alt=""/>
</carousel>

What the directive does is to simply create a <div class="carousel"> element into which the images are transcluded. Now, I still haven't coded the part where images slide or fade in/out cause there's one issues I'd like to get out of the way first: I want to assign the carousel and all the images therein the same height (computed as the height of the shortest image) so as to avoid the carousel from changing height when a taller image gets displayed, or avoid cropping the image in case the carousel had a fixed height.

So I jotted down this JSFiddle to demonstrate, but so far the best solution I found to compute the heights of the transcluded images relies on two nested $timeouts with a 100-ms delay. It looks to me more like a hack than anything.
So I was wondering if there's a "proper" way to accomplish it in angularjs. Cheers.

P.S. On a side note, I also dislike fetching the root element of the directive's template, the <div class="carousel"> in my case, using element.children()... is there no easy way to reference it in angularjs? Looked around but no dice.

share|improve this question
    
because without $timeout your directive will run before ng-repeat finishes rendering of img tags – Pankaj Parkar May 29 at 11:35
1  
Excellent approach, kudos. :) – Andrea Aloi May 30 at 10:35
    
Yes..I thought that I implemented that..& it works..Glad to help you..:) – Pankaj Parkar May 30 at 10:40
up vote 3 down vote accepted

You need to write one more directive that will be intimate angular code that ng-repeat rendered all the img tags then on that we will add listener event which will set the height and width of that element on load of that image.

Directive

.directive("carousel", ["$timeout", function ($timeout) {
    return {
        restrict: "E",
        transclude: true,
        template: "<div class=\"carousel\" ng-transclude></div>",
        link: function (scope, element, attrs) {
            var div = element.children();
            scope.$on('ngRepeatDone', function () {
                element.find('img').on('load', function () {
                    var images = div.children();
                    var minHeight = Math.min.apply(null, _.pluck(images, "height"));
                    angular.forEach([div, images], function (e) {
                        e.css({
                            height: minHeight + "px"
                        });
                    });
                    scope.$apply();
                });
            });
        }
    }
}])

NgRepeateDone

.directive('myPostRepeatDirective', function () {
    return function (scope, element, attrs) {
        if (scope.$last) {
            scope.$emit('ngRepeatDone')
        }
    };
});

Demo JSFiddle

share|improve this answer
1  
scope.$apply(); is good one here.....^^ – Jai May 29 at 11:55
    
@Jai yes..here we need it because we are doing scope manipulation on DOM event like here its .on('load') – Pankaj Parkar May 29 at 11:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.