"perfect-scrollbar" (jQuery plugin) isn't initialised properly when a its container is being filled with Angular.js

StackOverflow https://stackoverflow.com/questions/23279237

Question

On my page I programmatically generate a food/drinks menus from a json file with Angular.js. The problem is with the "perfect-scrollbar" used for scrolling the angular-generated content, which appears to require a scroll-wheel event to initialise on these menus. This makes it impossible to scroll on devices without a scroll-wheel. Apart from the angular-generated content other pages initialize perfect-scrollbar properly. This gave me a clue that the problem might lie with the interaction between jQuery world (perfect-scrollbar is a jQuery plugin) and Angular world.
The site is themockingbird.co.uk - navigate to the "Food" and "Drinks" to see the problem in action - can't scroll the content (the perfect-scrollbar won't appear) unless with the mouse scroll-wheel.
I've written this little directive:

mainMenuApp.directive('scrollBar', function(){
    return {
        restrict: 'C',
        template: '<div ng-transclude></div>',
        transclude: true,
        scope: {},
        link: function(scope, element, attrs){
            $(element).perfectScrollbar();
            //element.perfectScrollbar(); - doesn't work
            //angular.element(element).perfectScrollbar(); - doesn't work
        }
    }
});

to facilitate the "perfect-scrollbar" via angular for the two menus, but this did not solve the problem.
How can I make the perfect-scrollbar work perfectly with angular (pun intended :)?
I appreciate your time.
cheers
Jared

Était-ce utile?

La solution

At the time your link function is executed, your menu-food.json and menu-drink.json are not arrived yet and perfectScrollbar needs an update at the time the data arrive, called with:

$(element).perfectScrollbar('update');

Since you have no architecture for handling the food and drinks lists as decoupled watchable values in a controller attached by your directive, you may simply broadcast an event from the root scope, listened by your directive link functions, thus updating the perfectScrollbar instance at the right moment.

Autres conseils

I had the same problem when using https://github.com/itsdrewmiller/angular-perfect-scrollbar - the following "add-on directive", solved this problem:

.directive('psMouseOver', function () {    
    return {       
        link: function(scope, element) {
            element.bind("mouseover", function(e){
                e.stopPropagation();
                e.preventDefault();    
                element.perfectScrollbar('update');
            });   
        }
    }
});

In your case however, one would just add those lines and write your directive as:

mainMenuApp.directive('scrollBar', function(){
    return {
        restrict: 'A',
        template: '<div ng-transclude></div>',
        transclude: true,
        scope: {},
        link: function(scope, element, attrs){
            element.perfectScrollbar();
            element.bind("mouseover", function(e){
                e.stopPropagation();
                e.preventDefault();    
                element.perfectScrollbar('update');
            }); 
        }
    }
});

That happen in my case when Angular.js files loaded before JQuery and Perfect Scrollbar scripts files includes.

<script src="assets/libs/jquery.min.js"></script>
<script src="assets/libs/jquery.mousewheel.js"></script>
<script src="assets/libs/perfect-scrollbar.js"></script>

Try to load firstly JQuery, Perfect Scrollbar, and just after AngularJS.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top