33

CKEditorのテキストをテキストにバインドしたいng-model。私の見解:

    <form name="postForm" method="POST" ng-submit="submit()" csrf-tokenized class="form-horizontal">
  

    <fieldset>
    <legend>Post to: </legend>
    <div class="control-group">
      <label class="control-label">Text input</label>
      <div class="controls">
        <div class="textarea-wrapper">
          <textarea id="ck_editor" name="text" ng-model="text" class="fullwidth"></textarea>
        </div>
        <p class="help-block">Supporting help text</p>
      </div>
    </div>

    <div class="form-actions">
      <button type="submit" class="btn btn-primary">Post</button>
      <button class="btn">Cancel</button>
      <button class="btn" onclick="alert(ckglobal.getDate())">Cancel123</button>
    </div>
  </fieldset>
</form>

コントローラ

      function PostFormCtrl($scope, $element, $attrs, $transclude, $http, $rootScope) {
      $scope.form = $element.find("form");
      $scope.text = "";
    
      $scope.submit = function() {
          $http.post($scope.url, $scope.form.toJSON()).
          success(function(data, status, headers, config) {
                  $rootScope.$broadcast("newpost");
                  $scope.form[0].reset();
              });
      };
    
      $scope.alert1 = function(msg) {
          var sval = $element.find("ckglobal");
          //$('.jquery_ckeditor').ckeditor(ckeditor);                                                                                                                      
          alert(sval);
      };
    }
    PostFormCtrl.$inject = ["$scope", "$element", "$attrs", "$transclude", "$http", "$rootScope"];

$scope.textフォーム送信時にCKEditorの値を設定したい。

4

7 に答える 7

76

CKEditorは入力中にテキストエリアを更新しないので、注意する必要があります。

ng-modelバインディングをCKで機能させるディレクティブは次のとおりです。

angular.module('ck', []).directive('ckEditor', function() {
  return {
    require: '?ngModel',
    link: function(scope, elm, attr, ngModel) {
      var ck = CKEDITOR.replace(elm[0]);

      if (!ngModel) return;

      ck.on('pasteState', function() {
        scope.$apply(function() {
          ngModel.$setViewValue(ck.getData());
        });
      });

      ngModel.$render = function(value) {
        ck.setData(ngModel.$viewValue);
      };
    }
  };
});

HTMLでは、次を使用します。

<textarea ck-editor ng-model="value"></textarea>

前のコードは、変更のたびにng-modelを更新します。

保存時にバインディングを更新するだけの場合は、「save」プラグインをオーバーライドして、「save」イベントを発生させる以外は何もしません。

// modified ckeditor/plugins/save/plugin.js
CKEDITOR.plugins.registered['save'] = {
  init: function(editor) {
    var command = editor.addCommand('save', {
      modes: {wysiwyg: 1, source: 1},
      readOnly: 1,
      exec: function(editor) {
        editor.fire('save');
      }
    });

    editor.ui.addButton('Save', {
      label : editor.lang.save,
      command : 'save'
    });
  }
};

次に、ディレクティブ内でこのイベントを使用します。

angular.module('ck', []).directive('ckEditor', function() {
  return {
    require: '?ngModel',
    link: function(scope, elm, attr, ngModel) {
      var ck = CKEDITOR.replace(elm[0]);

      if (!ngModel) return;

      ck.on('save', function() {
        scope.$apply(function() {
          ngModel.$setViewValue(ck.getData());
        });
      });
    }
  };
});
于 2012-08-18T19:29:19.793 に答える
7

単にangularのエディターtextareaでテキストを取得したい場合CKEDITOR.instances.editor1.getData();は、angularjs関数で直接値を取得するために呼び出します。下記参照。

あなたのhtmlで

test.controller.jsで

(function () {
    'use strict';

    angular
        .module('app')
            .controller('test', test);

    test.$inject = []; 

    function test() {

        //this is to replace $scope
        var vm = this;

        //function definition
        function postJob()
        {          
            vm.Description = CKEDITOR.instances.editor1.getData();
            alert(vm.Description);
        }
    } 
})();
于 2015-01-09T00:54:33.623 に答える
6

Vojtaの回答は部分的に機能します

この投稿で私は解決策を見つけました

https://stackoverflow.com/a/18236359/1058096

最終的なコード:

.directive('ckEditor', function() {
                return {
                    require : '?ngModel',
                    link : function($scope, elm, attr, ngModel) {

                        var ck = CKEDITOR.replace(elm[0]);

                        ck.on('instanceReady', function() {
                            ck.setData(ngModel.$viewValue);
                        });

                        ck.on('pasteState', function() {
                            $scope.$apply(function() {
                                ngModel.$setViewValue(ck.getData());
                            });
                        });

                        ngModel.$render = function(value) {
                            ck.setData(ngModel.$modelValue);
                        };
                    }
                };
            })

編集:未使用のブラケットを削除

于 2013-09-01T02:47:53.250 に答える
1

優れた指令を提供してくれたVojtaに感謝します。時々それはロードされません。これは、その問題を修正するための修正バージョンです。

angular.module('ck', []).directive('ckEditor', function() {
  var calledEarly, loaded;
  loaded = false;
  calledEarly = false;

  return {
    require: '?ngModel',
    compile: function(element, attributes, transclude) {
      var loadIt, local;

      local = this;
      loadIt = function() {
        return calledEarly = true;
      };

      element.ready(function() {
        return loadIt();
      });

      return {
        post: function($scope, element, attributes, controller) {
          if (calledEarly) {
            return local.link($scope, element, attributes, controller);
          }
          loadIt = (function($scope, element, attributes, controller) {
            return function() {
              local.link($scope, element, attributes, controller);
            };
          })($scope, element, attributes, controller);
        }
      };
    },

    link: function($scope, elm, attr, ngModel) {
      var ck;
      if (!ngModel) {
        return;
      }

      if (calledEarly && !loaded) {
        return loaded = true;
      }
      loaded = false;

      ck = CKEDITOR.replace(elm[0]);
      ck.on('pasteState', function() {
        $scope.$apply(function() {
          ngModel.$setViewValue(ck.getData());
        });
      });

      ngModel.$render = function(value) {
        ck.setData(ngModel.$viewValue);
      };
    }
  };
});

または、コーヒースクリプトで必要な場合

angular.module('ck', []).directive('ckEditor', ->
  loaded = false
  calledEarly = false
  {
    require: '?ngModel',
    compile: (element, attributes, transclude) ->
      local = @
      loadIt = ->
        calledEarly = true

      element.ready ->
        loadIt()
      post: ($scope, element, attributes, controller) ->
        return local.link $scope, element, attributes, controller if calledEarly

        loadIt = (($scope, element, attributes, controller) ->
          return ->
            local.link $scope, element, attributes, controller
        )($scope, element, attributes, controller)
    link: ($scope, elm, attr, ngModel) ->
      return unless ngModel

      if (calledEarly and not loaded)
        return loaded = true
      loaded = false

      ck = CKEDITOR.replace(elm[0])

      ck.on('pasteState', ->
        $scope.$apply( ->
          ngModel.$setViewValue(ck.getData())
        )
      )

      ngModel.$render = (value) ->
        ck.setData(ngModel.$viewValue)
  }
)
于 2013-04-28T06:27:49.713 に答える
1

また、記録のために、1ページで複数のエディターを使用する場合は、これが便利です。

mainApp.directive('ckEditor', function() {
    return {
        restrict: 'A', // only activate on element attribute
        scope: false,
        require: 'ngModel',
        controller: function($scope, $element, $attrs) {}, //open for now
        link: function($scope, element, attr, ngModel, ngModelCtrl) {
            if(!ngModel) return; // do nothing if no ng-model you might want to remove this
            element.bind('click', function(){
                for(var name in CKEDITOR.instances)
                    CKEDITOR.instances[name].destroy();
                var ck = CKEDITOR.replace(element[0]);
                ck.on('instanceReady', function() {
                    ck.setData(ngModel.$viewValue);
                });
                ck.on('pasteState', function() {
                    $scope.$apply(function() {
                        ngModel.$setViewValue(ck.getData());
                    });
                });
                ngModel.$render = function(value) {
                    ck.setData(ngModel.$viewValue);
                };
            });
        }
    }
});

これにより、ckeditorの以前のすべてのインスタンスが破棄され、新しいインスタンスが作成されます。

于 2013-09-05T22:45:46.670 に答える
0

これに使用できる「変更」イベントがあります。

これが私が作成したばかりのディレクティブで、いくつかの異なるツールバー構成オプションがあります。jQueryアダプターを使用してckeditorを初期化しています。詳細については、このブログ投稿を確認してください。

(function () {
    'use strict';

    angular
        .module('app')
        .directive('wysiwyg', Directive);

    function Directive($rootScope) {
        return {
            require: 'ngModel',
            link: function (scope, element, attr, ngModel) {
                var editorOptions;
                if (attr.wysiwyg === 'minimal') {
                    // minimal editor
                    editorOptions = {
                        height: 100,
                        toolbar: [
                            { name: 'basic', items: ['Bold', 'Italic', 'Underline'] },
                            { name: 'links', items: ['Link', 'Unlink'] },
                            { name: 'tools', items: ['Maximize'] },
                            { name: 'document', items: ['Source'] },
                        ],
                        removePlugins: 'elementspath',
                        resize_enabled: false
                    };
                } else {
                    // regular editor
                    editorOptions = {
                        filebrowserImageUploadUrl: $rootScope.globals.apiUrl + '/files/uploadCk',
                        removeButtons: 'About,Form,Checkbox,Radio,TextField,Textarea,Select,Button,ImageButton,HiddenField,Save,CreateDiv,Language,BidiLtr,BidiRtl,Flash,Iframe,addFile,Styles',
                        extraPlugins: 'simpleuploads,imagesfromword'
                    };
                }

                // enable ckeditor
                var ckeditor = element.ckeditor(editorOptions);

                // update ngModel on change
                ckeditor.editor.on('change', function () {
                    ngModel.$setViewValue(this.getData());
                });
            }
        };
    }
})();

HTMLでディレクティブを使用する方法の例をいくつか示します。

<textarea ng-model="vm.article.Body" wysiwyg></textarea>
<textarea ng-model="vm.article.Body" wysiwyg="minimal"></textarea>

CDNから含めたCKEditorスクリプトと、Wordから画像を貼り付けるためにダウンロードしたいくつかの追加プラグインを次に示します。

<script src="//cdn.ckeditor.com/4.5.7/full/ckeditor.js"></script>
<script src="//cdn.ckeditor.com/4.5.7/full/adapters/jquery.js"></script>
<script type="text/javascript">
    // load extra ckeditor plugins
    CKEDITOR.plugins.addExternal('simpleuploads', '/js/ckeditor/plugins/simpleuploads/plugin.js');
    CKEDITOR.plugins.addExternal('imagesfromword', '/js/ckeditor/plugins/imagesfromword/plugin.js');
</script>
于 2016-04-28T03:05:38.150 に答える
0

CKEditorv5を使用したES6の例。

以下を使用してディレクティブを登録します。

   angular.module('ckeditor', []).directive('ckEditor', CkEditorDirective.create)

指令:

import CkEditor from "@ckeditor/ckeditor5-build-classic";
export default class CkEditorDirective {

   constructor() {
     this.restrict = 'A';
     this.require = 'ngModel';
   }

  static create() {
    return new CkEditorDirective();
  }

  link(scope, elem, attr, ngModel) {
    CkEditor.create(elem[0]).then((editor) => {
      editor.document.on('changesDone', () => {
        scope.$apply(() => {
          ngModel.$setViewValue(editor.getData());
        });
      });

      ngModel.$render = () => {
        editor.setData(ngModel.$modelValue);
      };

      scope.$on('$destroy', () => {
        editor.destroy();
      });
    })
  }
}
于 2017-10-17T08:47:16.447 に答える