ngRepeat - listening to element movement (I need to render a list of TinyMCE iframes with ngRepeat)

323 views
Skip to first unread message

Ivan S

unread,
Feb 19, 2014, 3:04:41 PM2/19/14
to ang...@googlegroups.com

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 somehow 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 between nested scopes in angular way?
How can my wysiwyg directive subscribe to the events from parent scopes if it cannot tell in advance whether it will be inside ng-repeat-custom or used on it's own?

Sander Elias

unread,
Feb 20, 2014, 2:39:36 AM2/20/14
to ang...@googlegroups.com
Hi Ivan,

Can you define 'moved in the DOM' for me? do you mean user-scroll? Do you mean dome elements get inserted before/after? Do you mean when it's inserted/removed itself?
do you mean drag&drop your widgets around?

Regards
Sander

Ivan Skryabin

unread,
Feb 20, 2014, 2:54:21 AM2/20/14
to ang...@googlegroups.com
Hi! Thanks for your attention!

By 'moving' i mean reordering of DOM elements which is implicitely done
by ngRepeat directive when the order of elements in collection changes.

For example:

<a ng-click="shuffleWidgets()">Shuffle</a>
<div ng-repeat="widget in widgets">
// Render widget with TinyMCE iframe inside
</div>

function controller($scope) {

widget1 = new Widget();
widget2 = new Widget();

$scope.widgets = [widget1, widget2];

// On some event:
$scope.shuffleWidgets = function() {
// Change the order of widgets to [widget2, widget1]
$scope.widgets[0] = [widget2];
$scope.widgets[1] = [widget1];

// ng-repeat will automatically reorder DOM elements, but
// iframes inside TinyMCE's will get reset because of this
// and i need to initialize them once again somehow when the
// reordering finishes
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "AngularJS" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/angular/sgeTMuZCXyQ/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> angular+u...@googlegroups.com.
> To post to this group, send email to ang...@googlegroups.com.
> Visit this group at http://groups.google.com/group/angular.
> For more options, visit https://groups.google.com/groups/opt_out.

Sander Elias

unread,
Feb 20, 2014, 3:04:51 AM2/20/14
to ang...@googlegroups.com

Ivan,

So the ‘reshuffeling’ is under control of your code. Then it’s easy enough. In your code, do a $scope.$emit('widgetsAreShuffled')
In your directive link function something like:

  scope.$on('widgetsAreShuffled', function () {
     // re-init your tiny-MCE
  });

if you need a start and stop event, that’s a bit more work, and you need to make sure that there is a digest cycle after your start event, but before you actually do anything.

Hope this helps a bit?
Regards
Sander

Ivan S

unread,
Feb 20, 2014, 7:04:14 AM2/20/14
to ang...@googlegroups.com
I like this approach!
But the question is, at what point in my code should i emit the event  scope.$emit('widgetsAreShuffled') ?

If i do this in controller just after I modified my widgets list, can I be sure that my widget directive recieves it AFTER the actual DOM modifications by ng-repeat and not immediately? 
Will scope.$emit() wait till the end of current digest cycle?

$scope.shuffleWidgets = function() { 
        // Change the order of widgets to [widget2, widget1] 
        $scope.widgets[0] = [widget2]; 
        $scope.widgets[1] = [widget1]; 

        scope.$emit('widgetsAreShuffled'); // <----   Can i be sure that directive recieves this event AFTER the DOM is modified by ng-repeat ?

Sander Elias

unread,
Feb 20, 2014, 10:52:50 AM2/20/14
to ang...@googlegroups.com

Hi Ivan,

hmm, not sure about it, just test it. If it does not work like you expected, put iy inside a timeout, liek this:

$timeout(function () {
   scope.$emit('widgetsAreShuffled');
},0);

that will put it in the NEXT digest cycle, probably the dom is done by then ;)

Regards
Sander

Ivan Skryabin

unread,
Feb 20, 2014, 11:30:38 AM2/20/14
to ang...@googlegroups.com
Great, many thanks!!!

I googled $timeout() and it turned out to be exactly what i was looking for!
Reply all
Reply to author
Forward
0 new messages