1

I am rendering a list of TinyMCE wysiwygs using ng-repeat directive:

<div ng-repeat="widget in wigdets">
   <textarea wysiwyg></textarea> <!-- This is a directive to initialize TinyMCE -->
</div>

When i change the order of widgets in controller, TinyMCE's instances are automatically rearranged accordingly.

The problem is that TinyMCE widget is an iframe and iframe state gets reset when it is moved in DOM.

So i need to save TinyMCE contents and remove TinyMCE from element before it is moved and then init TinyMCE once again and apply saved contents after the movement is finished.

Is there a simple way to somehow hook into ng-repeat and to register callbacks for element movement?

If I have to write my own ng-repeat-custom directive, what is the proper architecture to organize event dispatching in angular way?

Should I somehow send events to child directives? Or should child directives (wysiwyg in my case) subscribe to events of parent directives?

Chen-Tsu Lin
  • 22,876
  • 16
  • 53
  • 63
dr.scre
  • 2,287
  • 1
  • 22
  • 22

2 Answers2

1

Child directives to the parent should be discussed and ultimately include the full circle of directives for the use of both entities.

1

The problem actually boils down to "how i do something when ng-repeat finishes DOM manipulation". And I found the answer in similar question: Calling a function when ng-repeat has finished

In my case it's simple, because controller is in charge of modifing widgets list. So I can simply emit $scope.emit('pre_move') and $scope.emit('after_move') event and than handle them in my wysiwyg directive.

The important thing is to wrap 'after_move' in $timeout() ! It gurantees that execution will start in the next digest cycle and you can be sure that all DOM manipulation are finished by that time.

Controller:

function controller($scope, $timeout) {
    var widget1 = new Widget();
    var widget2 = new Widget();

    $scope.widgets = [widget1, widget2]

    $scope.emit('pre_move'); 

   // Shuffle widgets
   $scope.widgets[0] = widget2;
   $scope.widgets[1] = widget1;

   $timeout(function(){
        // $timeout wrapper is required to ensure that event will be emited 
        // in the next digest cycle
        $scope.emit('post_move');
   })

}

Wysiwyg TinyMCE directive:

link: function(scope, element, attrs) {
      ...

      var content;
      scope.on('pre_move', function() {
         content = element.html();
         element.tinymce().remove; // remove TinyMCE before movement
      });

      var content;
      scope.on('post_move', function() {
         element.tinymce().html(content); // reinitialize TinyMCE after movement
      });
}
Community
  • 1
  • 1
dr.scre
  • 2,287
  • 1
  • 22
  • 22