0

I'm doing a web app with Angular and Angular Material. I have to do a carousel and I found a nice jquery's component. So I made a directive with that. It works, but the problem is that for 1 or 2 seconds I see the elements of the carousel displayed like a <ul> list, so vertically. Then, when the directive is build, I see correctly the carousel.
Is there a way to insert a loader (maybe with angular material) that shows while the directive is not build?

This is the code

angular.module('app').directive("slick", function($timeout) {
        return function(scope: any, el: any, attrs: any) {
            $timeout((function() {
                el.slick({
                    arrows: true,
                    autoplay: false,
                    dots: true,
                    infinite: false,
                    speed: 300,
                    slidesToShow: 4,
                    slidesToScroll: 4,
                    responsive: [
                        {
                        breakpoint: 1024,
                        settings: {
                            slidesToShow: 3,
                            slidesToScroll: 3,
                            infinite: true,
                            dots: true
                        }
                        },
                        {
                        breakpoint: 600,
                        settings: {
                            slidesToShow: 2,
                            slidesToScroll: 2
                        }
                        },
                        {
                        breakpoint: 480,
                        settings: {
                            slidesToShow: 1,
                            slidesToScroll: 1
                        }
                        }
                        // You can unslick at a given breakpoint now by adding:
                        // settings: "unslick"
                        // instead of a settings object
                    ]
                })
            }), 100)
        }
    });
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
panagulis72
  • 2,129
  • 6
  • 31
  • 71
  • This doesn't answer the question but it's not good practise to mix jQuery with AngularJS (and Angular Material) - http://stackoverflow.com/a/30007955/782358 – camden_kid Jul 29 '16 at 16:12
  • @camden_kid I don't think that is always true. He is wrapping the whole thing in directive, which is the **correct** way of doing things in angular. Even the SO answer you posted says so, at point number 2. – CozyAzure Jul 29 '16 at 17:46
  • @CozyAzure Yeah, that's true. Wrapping it in a directive is the best way of doing it but I still think it not a good idea to mix the two. Still, needs must. – camden_kid Jul 29 '16 at 18:20

1 Answers1

0

I would use a boolean scope variable that tracks when slick is initialized. Start it at false, and use slick's init event to know when to set to true.

Basically:

angular.module('app').directive("slick", function($timeout) {
    return {
        restrict: 'E',
        replace: true,
        scope: true,
        templateUrl: 'slick.tpl.html',
        link: function(scope: any, el: any, attrs: any) {
            scope.slickReady = false;

            // use a child element (defined in template) so we can toggle between carousel and spinner
            var slickEl = el.children('.slick').first();
            if(slickEl){
                // listen for slick's init event 
                slickEl.on('init', function(){
                    scope.slickReady = true;
                });

                // initialize slick (not sure why you had it wrapped in $timeout in OP)
                slickEl.slick({
                    ...
                });
            }
        };
    }
});

slick.tpl.html

<div ng-switch on="slickReady">
    <div class="slick" ng-switch-when="true"></div>
    <div class="spinner" ng-switch-when="false">
        <!-- use whatever kind of spinner you want -->
    </div>
</div>
plong0
  • 2,140
  • 1
  • 19
  • 18
  • Thank you for the answer and sorry for the late! I tried to use your code, but I have an error: TypeError: el.querySelector is not a function – panagulis72 Aug 01 '16 at 07:23
  • I've found a solution for that error but it doesn't work yet. This is the slick.tpl:

    {{item.who}}

    and i've edited this on js: var slickEl = el[0].querySelector('.slick'); because, debugging it, the 'el' was so structured: 0:div length:1
    – panagulis72 Aug 01 '16 at 07:47
  • I've solved that error writing: $document.hasClass(".slick"); but the slick doesn't build... – panagulis72 Aug 01 '16 at 08:49
  • my bad... el is an angular.element, but element.querySelector is a core DOM method. Since we know you are loading jQuery, it is better to use `el.children('.slick').first()` (I've updated the answer with this change) – plong0 Aug 01 '16 at 18:39