2

Is it possible to apply two way binding to a <textarea></textarea> that has had TinyMCE applied to it for Rich Text Formatting.

I can't get it to work! I can get TinyMCE to load the content of my model, but when I update the text in TinyMCE, my model does not auto update!

Is there a way?

3 Answers 3

5

You can do this by creating your own directive.

What you need to do is to let your directive sync your model when something in the TinyMCE editor changes. I have not used TinyMCE, but Wysihtml5. I think you can remake this to use TinyMCE instead.

angular.module('directives').directive('wysihtml5', ['$timeout',
function ($timeout) {
    return {
        restrict: 'E',
        require: 'ngModel',
        template: "<textarea></textarea>", // A template you create as a HTML file (use templateURL) or something else...
        link: function ($scope, $element, attrs, ngModel) {

            // Find the textarea defined in your Template
            var textarea = $element.find("textarea");

            // When your model changes from the outside, use ngModel.$render to update the value in the textarea
            ngModel.$render = function () {
                textarea.val(ngModel.$viewValue);
            };

            // Create the editor itself, use TinyMCE in your case
            var editor = new wysihtml5.Editor(textarea[0],
                {
                    stylesheets: ["/style.css"],
                    parserRules: wysihtml5ParserRules,
                    toolbar: true,
                    autoLink: true,
                    useLineBreaks: false,
                });

            // Ensure editor is rendered before binding to the change event
            $timeout(function () {

                // On every change in the editor, get the value from the editor (textarea in case of Wysihtml5)
                // and set your model
                editor.on('change', function () {
                    var newValue = textarea.val();

                    if (!$scope.$$phase) {
                        $scope.$apply(function () {
                            ngModel.$setViewValue(newValue);
                        });
                    }
                });

            }, 500);
        }
    };
}]);

Then you can use the directive in your html page like this:

<wysihtml5 ng-model="model.text" />

Here's a link if you need more info on creating your own directive: http://docs.angularjs.org/guide/directive

Sign up to request clarification or add additional context in comments.

Comments

0

Also compare the render function from the directive above to this render function from angular-ui-tinymce ( https://github.com/angular-ui/ui-tinymce )

ngModel.$render = function() {
  if (!tinyInstance) {
    tinyInstance = tinymce.get(attrs.id);
  }
  if (tinyInstance) {
    tinyInstance.setContent(ngModel.$viewValue || '');
  }

Plnkr: http://plnkr.co/edit/04AFkp?p=preview

However depending on the timing of the loading of your DOM you may need to set the priority on your directive upwards. :-)

Comments

0

Here is my solution using a custom angular directive. You'll need to use jQuery with angularJS, TinyMCE 4 and their jQuery plugin.

myApp.directive('tinymce', function() {
   return {
      restrict: 'C',
      require: 'ngModel',
      link: function(scope, element, attrs, modelCtrl) {
         element.tinymce({
            setup: function (e) {
               e.on("change", function() {
                  modelCtrl.$setViewValue(element.val());
                  scope.$apply();
               }
            }
         });
      }
   }
}

Then in your HTML:

<textarea class="tinymce" ng-model="data"></textarea>

That's it, have fun.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.