Ich möchte den JavaScript-Editor CodeMirror in KnockoutJS integrieren. Ich weiß, dass es auch Ace gibt, aber es scheint mir mit CodeMirror einfacher zu sein.
Ich habe bereits benutzerdefinierte Bindungen für JQueryUI-Widgets und QTip integriert, aber das waren Code-Teile, die ich im Internet gefunden habe, und ich musste dann nur sehr kleine Teile modifizieren.
Leider scheint es, dass ich an meinen Grenzen bei Javascript angelangt bin. Daher wende ich mich hier JavaScript Sith Masters zu. Ich möchte nicht unbedingt, dass das Ganze für mich geschrieben wird, Hinweise und Ratschläge, wie ich weitermachen könnte, wären eine große Hilfe.
Das Stück Code, das ich habe:
Der HTML-Code (Ich habe die benutzerdefinierten Bindungen entfernt, die ich bereits im Textfeld habe, sie spielen hier keine Rolle)
%Vor%Der Beginn meines benutzerdefinierten Bindungshandlers für CodeMirror:
%Vor%Im Moment erzeugt dies keine JS-Fehler, aber 2 Textbereiche werden anstelle von einem angezeigt.
Was soll ich als nächstes tun?
Die vorher geposteten Lösungen scheinen etwas veraltet zu sein und würden für mich nicht funktionieren, also habe ich sie in einer Form umgeschrieben, die funktioniert:
%Vor% Mit <div data-bind="codemirror:fileContent"></div>
als Ziel für den Code-Mirror, der an diesen angehängt werden soll, wird eine neue Codemirror-Instanz erstellt und Optionen aus dem Ansichtsmodell übergeben, wenn sie festgelegt wurden.
[ edit ] Ich habe die Update-Methode des Codemirror-Binding-Handlers geändert, um den übergebenen valueAccessor auszupacken, ohne dass die Zeile knockout die Update-Methode nicht auslöst, wenn das Observable aktualisiert wird - es funktioniert jetzt du würdest es erwarten.
Der Code, der von Jalayn aufgelistet wird (oder einer in jsfiddle), aktualisiert die Beobachtungsvariable nicht, auch der Editor zeigt den Wert beim Laden nicht an. Hier ist mein aktualisierter Code
%Vor%Nun, ich habe es endlich geschafft (siehe die aktualisierte Geige ).
Ich habe es schnell geschafft, den Anfangswert im benutzerdefinierten Textfeld festzulegen. Aber danach wurde das gebundene Element nicht aktualisiert.
Allerdings können Sie mit der API von CodeMirror eine Callback-Methode für das Ereignis onChange
registrieren, das aufgerufen wird, wenn der Inhalt des Textfelds geändert wird. Es ging also nur darum, den Callback zu implementieren, der den Wert des gebundenen Elements aktualisiert. Dies geschieht bei der Erstellung des benutzerdefinierten Textbereichs in den Optionen.
Hier ist die benutzerdefinierte Bindung:
%Vor%Es mag vielleicht einige Funktionen fehlen, aber für das, was ich brauche, funktioniert es perfekt.
Bearbeiten: Nach der Bemerkung von Anders habe ich den addDisposeCallback
-Teil hinzugefügt, der das von CodeMirror erzeugte DOM-Element effektiv zerstört, wenn die Vorlage erneut gerendert wird. Da alles, was CodeMirror erzeugt, innerhalb eines Knotens liegt, muss nur dieser Knoten entfernt werden.
Ich hatte ein Problem mit dem Cursor auf die erste Position gesetzt. Diese Geige behebt dies und akzeptiert auch CodeMirror options
object als bindenden Wert, und der Inhalt ist an eine options.value
Observable gebunden (Ich finde das weniger verwirrend, weil das eigentlich der Name der Eigenschaft ist, von der CM den Startwert erhält)
Beispiel HTML:
%Vor%Ich versuche, den Binding-Handler oben zu verwenden, aber ich habe ein Problem mit keinem Text in der TextArea, bis ich etwas (ein Leerzeichen oder ein anderes Zeichen) eingeben.
Es ist leer, wenn das Laden abgeschlossen ist, und sobald ich etwas in den Bereich eingebe, werden alle gebundenen Daten sichtbar.
Noch eine Frage, wenn ich eine einfache ko.observable () an den Wert von TextArea binde, funktioniert alles gut, aber wenn ich dies durch eine der Spalten in einem ko.observableArray, z. Wert: selectedProfile (). QueryString, ich bekomme den folgenden Fehler vom Bindungshandler:
Zeile in Frage: editor.setValue (allBindingsAccessor (). value ()); Fehler: Uncaught TypeError: Eigenschaft 'Wert' von Objekt # ist keine Funktion
Gedanken?
/ LM
Ich stoße auf das gleiche Problem wie Lars in einer der obigen Antworten, d. h. Codemirror lud die Daten zunächst nicht bis zur ersten Interaktion ein. Ich habe es gelöst, indem ich ein Flag hinzugefügt habe, um festzustellen, ob sich der Codemirror-Wert durch Eingabe oder Programmatierung geändert hat, und zeichne den Wert ab.
%Vor%Ich glaube, es würde eine "sauberere" Methode geben, um dasselbe zu erreichen, aber das scheint vorerst in Ordnung zu sein.
Tags und Links knockout.js javascript codemirror