0

这是我们最近在项目中遇到的错误的简化示例。

我有一个具有“名称”和“位置”属性的对象列表,并且想使用 TinyMCE 编辑器而不是 textarea 来显示“名称”。

此外,列表按可编辑的“位置”属性排序。

请注意,一旦“位置”属性更改(列表重新排序),TinyMCE 编辑器就会变为空。

任何人都有任何想法为什么会发生以及如何解决这个问题?

示例代码:JsFiddle

HTML

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script src="//tinymce.cachefly.net/4.1/tinymce.min.js"></script>
<body ng-app="myApp">
    <div ng-controller="MyCtrl">
        <p>List of activities:</p>
        <div ng-repeat="activity in model.activities | orderBy: 'position'">
             <label for="$index">Position</label>
            <input id="$index" type="number" ng-model="activity.position" style="width: 50px">
            <textarea ng-model="activity.name" ui-tinymce="tinyMceOptions" rows="2" cols="10"></textarea>

            <hr>
        </div>
    </div>
</body>

JS

var myApp = angular.module('myApp', ['ui.tinymce']);
/**
 * Binds a TinyMCE widget to <textarea> elements.
 */
angular.module('ui.tinymce', [])
  .value('uiTinymceConfig', {})
  .directive('uiTinymce', ['uiTinymceConfig', function (uiTinymceConfig) {
    uiTinymceConfig = uiTinymceConfig || {};
    var generatedIds = 0;
    return {
      priority: 10,
      require: 'ngModel',
      link: function (scope, elm, attrs, ngModel) {
        var expression, options, tinyInstance,
          updateView = function () {
            ngModel.$setViewValue(elm.val());
            if (!scope.$root.$$phase) {
              scope.$apply();
            }
          };

        // generate an ID if not present
        if (!attrs.id) {
          attrs.$set('id', 'uiTinymce' + generatedIds++);
        }

        if (attrs.uiTinymce) {
          expression = scope.$eval(attrs.uiTinymce);
        } else {
          expression = {};
        }

        // make config'ed setup method available
        if (expression.setup) {
          var configSetup = expression.setup;
          delete expression.setup;
        }

        options = {
          // Update model when calling setContent (such as from the source editor popup)
          setup: function (ed) {
            var args;
            ed.on('init', function(args) {
              ngModel.$render();
              ngModel.$setPristine();
            });
            // Update model on button click
            ed.on('ExecCommand', function (e) {
              ed.save();
              updateView();
            });
            // Update model on keypress
            ed.on('KeyUp', function (e) {
              ed.save();
              updateView();
            });
            // Update model on change, i.e. copy/pasted text, plugins altering content
            ed.on('SetContent', function (e) {
              if (!e.initial && ngModel.$viewValue !== e.content) {
                ed.save();
                updateView();
              }
            });
            ed.on('blur', function(e) {
                elm.blur();
            });
            // Update model when an object has been resized (table, image)
            ed.on('ObjectResized', function (e) {
              ed.save();
              updateView();
            });
            if (configSetup) {
              configSetup(ed);
            }
          },
          mode: 'exact',
          elements: attrs.id
        };
        // extend options with initial uiTinymceConfig and options from directive attribute value
        angular.extend(options, uiTinymceConfig, expression);
        setTimeout(function () {
          tinymce.init(options);
        });

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

        scope.$on('$destroy', function() {
          if (!tinyInstance) { tinyInstance = tinymce.get(attrs.id); }
          if (tinyInstance) {
            tinyInstance.remove();
            tinyInstance = null;
          }
        });
      }
    };
  }]);

myApp.controller("MyCtrl", ["$scope", function($scope) {
    $scope.model = { 
        activities: [
            {name: "activity 1", position: 1}, 
            {name: "activity 2", position: 2}, 
            {name: "activity 3", position: 3}, 
            {name: "activity 4", position: 4}, 
            {name: "activity 5", position: 5}
        ] 
    };
    $scope.tinyMceOptions = {
        selector: "textarea",
        theme: "modern",
        plugins: [
            "autolink lists link charmap print preview hr anchor pagebreak autoresize",//advlist
            "searchreplace visualblocks visualchars code",
            "insertdatetime nonbreaking save table directionality",
            "emoticons template paste textcolor colorpicker textpattern"
        ],
        toolbar1: "bold italic underline |  alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | forecolor backcolor | undo redo | link | pastetext",
        paste_auto_cleanup_on_paste: true,
        paste_strip_class_attributes: 'mso',
        paste_data_images: false,
        theme_advanced_buttons3_add: "pastetext,pasteword,selectall",
        image_advtab: true,
        //templates: [
        //    {title: 'Test template 1', content: 'Test 1'},
        //    {title: 'Test template 2', content: 'Test 2'}
        //],
        browser_spellcheck: true,
        menubar: false,
        //theme_advanced_disable: "bullist,numlist",
        target_list: [{ title: 'New page', value: '_blank' }],
        //advlist_number_styles: [
        //    {title : 'Standard', styles : {listStyleType : ''}},
        //    {title : 'a. b. c.', styles : {listStyleType : 'lower-alpha'}}
        //],
        //spellchecker_languages: "+English=en",
        //spellchecker_rpc_url: 'spellchecker.php',
        handle_event_callback: function (e) {
            // put logic here for keypress
        }
    };
}]);
4

0 回答 0