Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Reframe codemirror
(ns mything.components.codemirror
(:require [reagent.core :as reagent]
[re-frame.core :as rf]
[reagent.interop :refer [$]]
cljsjs.codemirror
cljsjs.codemirror.mode.clojure
cljsjs.codemirror.mode.sql))
(def codemirror-defaults {:lineNumbers true
:lineWrapping true
:styleActiveLine true
:mode "text/x-mssql"
:tabMode "spaces"})
(defn create-editor [this editor options value dispatch-path dims]
(let [cm (.fromTextArea js/CodeMirror
(reagent/dom-node this)
(clj->js (merge codemirror-defaults options)))]
(when value
($ cm setValue value))
($ cm setSize (:width dims) (:height dims))
($ cm on "change"
(fn [ed]
(rf/dispatch-sync (conj dispatch-path ($ ed getValue)))))
(reset! editor cm)))
(defn destroy-editor [editor]
(if @editor
(do (.toTextArea @editor)
(reset! editor nil))
(js/console.warn "Could not kill CodeMirror instance")))
(defn codemirror-editor
([{:keys [value dispatch-path options textarea-obj dims]
:or [value "", dispatch-path [], options {}, textarea-obj {}, dims {:height nil, :width nil}]}]
(let [editor (atom nil)]
(reagent/create-class
{:component-did-mount (fn [this] (create-editor this editor options value dispatch-path dims))
:component-will-unmount (fn [this] (destroy-editor editor))
:component-did-update (fn [this [_ {prev-dispatch-path :dispatch-path,
prev-options :options,
prev-textarea-obj :textarea-obj,
prev-dims :dims}]]
(let [{:keys [value dispatch-path options textarea-obj dims]} (reagent/props this)
editor-val ($ @editor getValue)]
(if-not (and (= prev-dispatch-path dispatch-path)
(= prev-options options)
(= prev-textarea-obj textarea-obj))
;; big prop change where the others will be set
(do (destroy-editor editor)
(create-editor this editor options value dispatch-path dims))
;; set value and dimensions individually if updated
;; editor setValue chokes for nil values
(do (when-not (= editor-val value)
($ @editor setValue (or value "")))
(when-not (and (= prev-dims dims))
($ @editor setSize (:width dims) (:height dims)))))))
:reagent-render (fn [] [:textarea textarea-obj])}))))
(comment
;; Usage
[codemirror-editor {:value query
:options {:mode "clojure" :lineNumbers true}
:dispatch-path [::change-dev-update]}])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment