egervari egervari - 7 days ago 5
AngularJS Question

Angular UI Tinymce deletes content from ng-model and 2-way binding does not work when not using `<textarea>`

One problem I am having with TinyMCE editor and Angular UI's light wrapper is that ng-model doesn't appear to do the 2-way binding that I would expect with the model data on the scope when changes are made in the editor. This problem only seems to happen when

<div>
or
<p>
is used.

The 2-way binding seems to work just fine when I use
<textarea>
, but this is not what I want... I want an inline editor.

Here are my options:

$scope.tinymceOptions = {
inline: true,
menubar: false,
statusbar: false,
toolbar: "bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link | removeformat"
};


In my case, if there is content in
pageElement.text
, it will actually get put into the TinyMCE editor just fine. However, once TinyMCE does this, the text is deleted from
pageElement.text
altogether, and the
ng-model
binding that it has to
pageElement.text
is no longer being respected:

<div class="pageParagraph">
<div class="contenteditable"
ui-tinymce="tinymceOptions"
ng-model="pageElement.text"></div>
<p>{{pageElement}}</p>
</div>


Here's a screenshot:

Displaying inline problem

How can I get 2-way binding to occur when TinyMCE is in inline mode?

Answer

After an hour or so of mucking around, I figured that changing updateView in tinymce.js from the Angular UI extension fixes the issue:

      updateView = function () {
        if(elm.prop("tagName").toLowerCase() === 'textarea') {
            ngModel.$setViewValue(elm.val());
        } else {
            ngModel.$setViewValue(elm.html());
        }

        if (!scope.$$phase) {
          scope.$apply();
        }
      };

It's probably not perfect, but it will work for p, div and textarea. This solution also avoids non-obvious code that looks strange.

Comments