-->

AngularJS ngRepeat and jQuery - DOM rebuilding iss

2019-09-03 14:58发布

问题:

I am very well aware how mixing angularjs and jquery is NOT a good idea. However, I need a custom carousel, which could slide through TEXT ONLY. All the existing carousel animations for angularjs depend heavily on image being part of the content, whereas I have no images. So I found a very good jquery library for such a thing, called "slick".

It works well with angularjs, but when I dynamically ADD new values to an existing array, the whole thing breaks apart. How could I change this part of code so that I could dynamically add objects to array AND keep jquery slick library working?

Here's the code, you can press "prev" and "next" and carousel will work, but as soon as you press ADD NEW ELEMENT button, the whole thing falls apart. http://jsbin.com/tihodihuho/1/edit?html,js,output

回答1:

You need to make sure that by the time your call the jQuery functions unslick and slick the DOM has already been rendered.

You can accomplish that by having those functions inside a $timeout function (with delay 0, of course). That will ensure that the code inside the $timeout function will get executed after the $diggest cycle has finished.

Try this:

Example

controller('myCtrl', ['$timeout',function($timeout){ 
  var self = this;  
  self.data = [{
        id: 1,
        title: 'A title, representing part 1',
        text: 'This is my TEXT 1'
      },
      {
        id: 2,
        title: 'Anoter interesting title that will grab your attention',
        text:'...and even longer text!'
      }];

  self.next =function() {
    $('.your-class').slickNext();
  };

  self.prev =function() {
    $('.your-class').slickPrev();
  };

  self.add = function() {
    var newID = self.data.length + 1;
    self.data.push({
      id:newID,
      title:'A totally new object!',
      text:'Dynamically added object to an existing array.'
    });   
    $timeout(function(){      
      $('.your-class').unslick();
       $('.your-class').slick({
        autoplay: false,
        autoplaySpeed: 1500,
        swipeToSlide: true
      });            
    });
  };
}]);

UDATE

In order to fix the issue that the OP described in the comments bellow, and that it's completely unrelated with the original question I've came up with this workaround:

$timeout(function(){            
  $('.your-class').unslick();

  //You would think that `unslick` would take care of this, but it didn't so: 
  $('.your-class .slick-cloned, .your-class .slick-list.draggable').remove();

  //this is a workaround, which proves that the issue was with the plugin
  //nothing to do with the original question. In order to address this properly the
  //OP should open a new question or a bug in the `unslick` plugin.

   $('.your-class').slick({
    autoplay: false,
    autoplaySpeed: 1500,
    swipeToSlide: true
  });            
});

Example