angularjsangularjs-ng-routemixitup

jQuery MixItUp with AngularJS NgRoute


I managed to integrate jQuery MixItUp into my AngularJs app.

The items that should be displayed with MixItUp are loaded from custom services. Once all items are fetched, i trigger instantiation of jQuery MixItUp.

I'm also using AngularJS NgRoute to implement different pages.
When i first visit the page where jQuery MixItUp is used everything is fine. But when i then go to another page and back to the page with jQuery MixItUp, the filters and sorting aren't working anymore.

I setup my routes like this:

myApp
.config(function($routeProvider, $locationProvider) {
    $routeProvider

        // some routes for other pages
        .when('/', {
            templateUrl : '/assets/js/app/views/home.html',
            controller  : 'MainController'
        })
        .when('/about', {
            templateUrl : '/assets/js/app/views/about.html',
            controller  : 'AboutController'
        })

        // route for page where MixItUp is used
        .when('/media', {
            templateUrl : '/assets/js/app/views/media.html',
            controller  : 'MediaController'
        })

        // 404
        .otherwise({
            redirectTo  : '/404'
        })

    $locationProvider.html5Mode(true);
});

In my custom directive i init jQuery MixItUp with some options and fix sorting after init. The console.log are logging to console everytime i visit or revisit the page. But on revisit the functionality of filters and sorting are broken. The custom directive looks like this:

myApp
.directive('mixitup', function($compile) {

    return {
        restrict: 'A',
        link: function(scope, element, attrs) {

            scope.$on('init-mixitup', function(event) {
                console.log('[event] înit-mixitup');
                angular.element(element).mixItUp({
                    animation: {
                        duration: 200
                    },
                    load: {
                        sort: 'myorder:desc'
                    },
                    debug: {
                        enable: true,
                        mode: 'normal'
                    }
                });
            });

            scope.$on('resort-mixitup', function(event, sortCommand) {
                console.log('[event] resort-mixitup');
                angular.element(element).mixItUp('sort', sortCommand);
            });
        }
    };
});

In my AngularJS Controller (MediaController) i broadcast the events once all items are fetched from custom services:

// init
$rootScope.$broadcast('init-mixitup');

// sort
$rootScope.$broadcast('resort-mixitup', 'myorder:desc');

The view HTML looks like this:

<div class="btn-group controls">
    <button class="btn btn-lg filter"
        data-filter="all">All</button>
    <button class="btn btn-lg filter"
        data-filter=".photo">Photo</button>
    <button class="btn btn-lg filter"
        data-filter=".audio">Audio</button>
    <button class="btn btn-lg filter"
        data-filter=".video">Video</button>
</div>

<div mixItUp="mixItUp" id="mixitup-container">
    <div ng-repeat="item in items"
        id="{{ item.id }}"
        style="display: inline-block;"
        data-myorder="{{ item.date }}"
        class="mix col-xs-6 col-sm-4 {{ item.category }}">
            <img ng-src="{{ item.image }}" class="img-responsive img-circle">
    </div>
</div>

The Javascript console in chrome outputs the following on first page load:

[event] înit-mixitup
[MixItUp][mixitup-container][_bindHandlers] 4 filter buttons found.
[MixItUp][mixitup-container][_init] MixItUp instantiated on container with ID "mixitup-container".
[MixItUp][mixitup-container][_init] There are currently 1 instances of MixItUp in the document.
[event] resort-mixitup
[MixItUp][mixitup-container][multiMix] Operation requested via the API.
[MixItUp][mixitup-container][multiMix] An operation was requested but MixItUp was busy. The operation was added to the queue in position 1.
[MixItUp][mixitup-container][multiMix] Loading operation from queue. There are 0 operations left in the queue.
[MixItUp][mixitup-container][multiMix] Operation requested via the API.
[MixItUp][mixitup-container][multiMix] Operation started.
[MixItUp][mixitup-container][_cleanUp] Loading animation completed successfully.
[MixItUp][mixitup-container][_cleanUp] The operation completed successfully.

And on second page load (after moving to other pages, without browser reload):

[event] înit-mixitup
[event] resort-mixitup
[MixItUp][mixitup-container][multiMix] Operation requested via the API.
[MixItUp][mixitup-container][multiMix] Operation started.

There is another question relating this issue here: How to initiate MixItUp with AngularJS NgRoute But there the items aren't loaded dynamically via custom services.


Solution

  • I fixed the issue by calling jQuery MixItUp destroy function when leaving the page.

    I added another event listener to my directive for MixItUp:

    myApp
    .directive('mixitup', function($compile) {
    
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
    
                scope.$on('init-mixitup', function(event) {
                    // console.log('[event] înit-mixitup');
                    angular.element(element).mixItUp({
                        animation: {
                            duration: 200
                        },
                        load: {
                            sort: 'myorder:desc'
                        }
                    });
                });
    
                scope.$on('resort-mixitup', function(event, sortCommand) {
                    // console.log('[event] resort-mixitup');
                    angular.element(element).mixItUp('sort', sortCommand);
                });
    
                scope.$on('destroy-mixitup', function(event) {
                    // console.log('[event] destroy-mixitup');
                    angular.element(element).mixItUp('destroy');
                })
            }
        };
    });
    

    And also added the event trigger in my AngularJS Controller (MediaController):

    $scope.$on("$destroy", function(){
        $rootScope.$broadcast('destroy-mixitup');
    });