How to initiate MixItUp with AngularJS NgRoute

2019-02-22 03:27发布

问题:

I've been setting up a jquery plugin MixItUp with AngularJS and although I can successfully initiate the container during one of my partial views with NgRoute, once I move to other page views and go back it seems that MixItUp does not know how to initiate setup again.

I’ve tried $(document).ready(), $(window).load, and even $viewContentLoaded but nothing seems to make it work. The whole container simply does not get called when I click on my other pages and return again.

My code as below.

$scope.$on('$viewContentLoaded', function(){  

    $('#container').mixItUp();    

    var $container = $('#ContainerP');

    if(!$container.mixItUp('isLoaded')){
      $container.mixItUp();
    } 
  alert("It's loading!");
});

Everything in the function passes smoothly including the alert message, but somehow mixItUp cannot be called within my routing views…would appreciate greatly if someone could help me out here! Thanks!

回答1:

As @demkalkov suggest use a directive and load mix-it-up related html as template like

.directive('mixItUp', function(){
    return{
      restrict: 'AEC',
      templateUrl: 'mix-it-up-tpl.html',
      link: function(scope, element){             
         $(element).mixItUp();
      }
    }
  })

Use the directive in html as

<div mix-it-up></div>

And lets say your mix-it-up.html looks like

<div id="Container" class="container">
  <div class="mix category-1" data-myorder="1"></div>
  <div class="mix category-1" data-myorder="2"></div>
</div

Here is a working Demo

Note - In Angular context directive is the ideal place to manipulate html or plugin integration.



回答2:

I integrated jQuery MixItUp with AngularJS NgRoute with the use of a custom directive.

I use the AngularJS $broadcast and $on functions to handle communication between Controller and Directive:

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');
            })
        }
    };
});

My view HTML:

<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>

In my controller handle jQuery MixItUp with the following calls:

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

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

You have to destroy jQuery MixItUp when leaving page. I managed this by adding the following to my controller:

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

You can also have a look at a very similar question i posted myself: jQuery MixItUp with AngularJS NgRoute



回答3:

I'd recommend you to use directives when you are working with DOM. So you need to create some directive that will initiate MixItUp for you

angular.module('app').directive('myNgMixitup', [function(){
   return {
      restrict: 'AEC',
      link: function(scope, element){
         //now you can access the element/container
         element.mixItUp();
      }
   };
}])


回答4:

I spent several hours and finally the solution is here....

if ($('#grid').mixItUp('isLoaded')) {
          $('#grid').mixItUp('destroy');
          $('#grid').mixItUp();
      } else {
        $('#grid').mixItUp();
      }

Here's the full directive code..

'use strict';
 angular.module('rjApp')
.directive('mixitup',function($timeout,$compile){
  var linker = function(scope,element,attr) {

    scope.$watch('entities', function(newVal, oldVal){

      $timeout(function(){
        if ($('#grid').mixItUp('isLoaded')) {
            $('#grid').mixItUp('destroy');
            $('#grid').mixItUp();
        } else {
          $('#grid').mixItUp();
        }
      },10);
    },true);

  };
  return {
    link: linker,
    scope:{entities:'='}
  }
})