it-swarm.com.de

Aktualisieren des Textbereichs mit CKEditor-Inhalten in Angular JS

Ich verwende den neuesten CKEditor (Standard Version) und basierend auf dieser Frage habe ich eine Winkelrichtlinie wie folgt implementiert:

var cmsPlus = angular.module('cmsPlus', []);

cmsPlus.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);
      };
    }
  };
});

Es funktioniert einwandfrei, wenn ich etwas im CKEditor-GUI-Modus eingebe. Hier bekomme ich den eingetippten Inhalt in das NG-Modell von textarea. 

Wenn ich jedoch zum Code-Editor wechsle, wird der aktualisierte Inhalt auch nach dem Wechsel zur GUI nicht angezeigt. Es ist erforderlich, etwas im grafischen Modus erneut einzugeben.

Was stimmt nicht mit meiner Anweisung? Oder kann ich diese Direktive um einige andere CKEditor-Ereignisse erweitern?

Ich möchte noch weitere Ereignisse für das Formular einreichen oder etwas anderes hinzufügen.

Demo hier.

14
devo

Ihre Anweisung funktioniert gut.

Es gibt ein Plugin namens sourcearea , das das Verhalten des CKEditor während Quellmodus steuert. Ich konnte kein Ereignis im Code dieses Plugins für die Verarbeitung von Eingaben auslösen. Es gibt jedoch zwei Ereignisse, die wir erfassen können, wenn der CKEditor zu GUI-Modus zurückkehrt. Die Ereignisse sind ariaWidget und dataReady .

Ich habe Ihr Beispiel so aktualisiert, dass das Ereignis dataReady verwendet wird, sodass der Textbereich beim Zurückschalten aktualisiert wird. Ich habe auch das pasteState event in change geändert, wie Dan Caragea sagte es wurde in Version 4.2 eingeführt. Die aktualisierte Geige ist hier zu finden

Eine fast existierende Lösung, die ich gefunden habe, ist das key -Ereignis zu hören und das Modell zu aktualisieren. Es ist fast da, weil es scheint, als würde das Ereignis nur für die alte gedrückte Taste ausgelöst. Der letzte Schlüssel fehlt also immer.

var cmsPlus = angular.module('cmsPlus', []);

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

      if (!ngModel) return;

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

      function updateModel() {
          scope.$apply(function() {
              ngModel.$setViewValue(ck.getData());
          });
      }

      ck.on('change', updateModel);
      ck.on('key', updateModel);
      ck.on('dataReady', updateModel);

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

Auf jeden Fall können Sie vielleicht herausfinden, wie Sie das letzte Schlüsselproblem beheben können. Es ist fast da!

BEARBEITEN: aktualisierter Geigen-Link zur korrekten Version

27
Jonas

Ich weiß, dass diese Frage bereits beantwortet wurde, aber ich dachte, ich würde mich darauf einlassen, was ich tun musste, um CKEditor 4.4.4 mit Angularjs 1.2 zu integrieren. Hier ist mein Code in Kaffeescript:

'use strict'

angular.module 'core', []

.directive 'ckeditor', ->
    require: '?ngModel'
    link: (scope, element, attrs, ngModel) ->
        config =
            # CKEditor config goes here

        editor = CKEDITOR.replace element[0], config

        return unless ngModel

        editor.on 'instanceReady', ->
            editor.setData ngModel.$viewValue

        updateModel = ->
            scope.$apply ->
                ngModel.$setViewValue editor.getData()

        editor.on 'change', updateModel
        editor.on 'dataReady', updateModel
        editor.on 'key', updateModel
        editor.on 'paste', updateModel
        editor.on 'selectionChange', updateModel

        ngModel.$render = ->
            editor.setData ngModel.$viewValue

Für das Kaffeeskript-Analphabet ist hier das kompilierte Javascript:

'use strict';
angular.module('core', []).directive('ckeditor', function() {
    return {
      require: '?ngModel',
      link: function(scope, element, attrs, ngModel) {
        var config, editor, updateModel;
        config = {
            // CKEditor config goes here
        }
        editor = CKEDITOR.replace(element[0], config);
        if (!ngModel) {
          return;
        }
        editor.on('instanceReady', function() {
          return editor.setData(ngModel.$viewValue);
        });
        updateModel = function() {
          return scope.$apply(function() {
            return ngModel.$setViewValue(editor.getData());
          });
        }};
        editor.on('change', updateModel);
        editor.on('dataReady', updateModel);
        editor.on('key', updateModel);
        editor.on('paste', updateModel);
        editor.on('selectionChange', updateModel);
        return ngModel.$render = function() {
          return editor.setData(ngModel.$viewValue);
        };
      }
    };
  }
);

Dann im HTML:

<textarea ckeditor data-ng-model="myModel"></textarea>

Nun zur Erklärung.

Ich habe der Vollständigkeit halber Einfüge- und Auswahländerungshandler hinzugefügt, aber es stellte sich heraus, dass der Auswahländerungshandler notwendig war. Ich entdeckte, dass, wenn ich alles auswählte und auf "Löschen" klickte, das Formular ohne Änderung des Fokus des Editors gesendet wurde und die Änderungen beim Senden nicht im Modell berücksichtigt wurden. Der Auswahländerungshandler löst dieses Problem.

Die Integration von CKEditor in Angularjs ist für mein Projekt von entscheidender Bedeutung. Wenn ich also mehr "Gotchas" finde, werde ich diese Antwort aktualisieren.

9
Mjonir74

Ich hoffe, das Problem ähnelt meinem: Der CK-Editor verfügt über eigene Elemente, die er in das DOM einfügt, und Angular ist bereits gerendert, sodass Sie einen Listener für wann einrichten müssen Es geht in den Code-Editor über. Wenn Sie nicht auf die Änderung achten, kann Angular nicht ordnungsgemäß gebunden werden, da die Änderungen im DOM nicht bekannt sind. Ich hatte etwas Ähnliches mit Tinymce und der Modalität, die auftaucht.

Hier ist eine weitere Ressource, die mit meinem Problem zusammenhängt

0
dasper

Für mich funktionierte die Antwort von @ Mjonir74, aber sobald ich mehrere Editor-Instanzen auf einer Seite hatte und auch den Bearbeitungsmodus nicht nur im Erstellungsmodus berücksichtigen musste, funktionierten die Dinge nicht mehr richtig, wenn Sie zur Seite zurückkehrten den Editor enthalten. Grundsätzlich im Bearbeitungsmodus war das erste Mal, als Sie die Seite besuchten, alles in Ordnung, der Text befand sich wie erwartet im Editor. Bei aufeinanderfolgenden Besuchen auf derselben Seite blieb der Editor leer, kein Text.

So hat es für mich funktioniert:

    app.directive('appWysiwygBlock', function() {
    return {
        require: 'ngModel',
        restrict: 'E',
        templateUrl: 'modules/app/templates/directives/wysiwyg-block.html',
        scope: {
            error: '=',
            config: '='
        },
        link: function(scope, element, attrs, ngModel) {

            if (typeof CKEDITOR == 'undefined' || !ngModel) {
                return;
            }

            scope.required = attrs.required || false;
            scope.cols = attrs.cols || 6;

            scope.label = attrs.label || attrs.name;
            scope.name = attrs.name || scope.label;
            if (scope.name) {
                scope.name = scope.name.toLowerCase().replace(/[^a-z0-9]/gi, '_');
            }

            var defaultConfig, config, editor, updateModel;

            config = scope.config || {};
            defaultConfig = {
                customConfig: '/modules/app/ckeditor-config.js'
            };

            config = element.extend({}, defaultConfig, config);
            editor = CKEDITOR.replace(element.find('textarea:first')[0], config);

            updateModel = function() {
                return scope.$apply(function() {
                    return ngModel.$setViewValue(editor.getData());
                });
            };

            editor.on('instanceReady', function() {
                editor.on('change', updateModel);
                editor.on('dataReady', updateModel);
                editor.on('key', updateModel);
                editor.on('paste', updateModel);
                editor.on('selectionChange', updateModel);
                return editor.setData(ngModel.$viewValue);
            });

            return ngModel.$render = function() {
                return editor.setData(ngModel.$viewValue);
            };
        }
    };
});

und ich benutze es als 

<app-wysiwyg-block label="Description" name="description" ng-model="item.description" error="fieldErrors.description" required="true" cols="12"></app-wysiwyg-block>

beliebig oft auf einer Seite und funktioniert in allen Modi einwandfrei.

0
Twisted1919