From 305fc73d8a2de78a64d62de95eee1e9a57181716 Mon Sep 17 00:00:00 2001 From: Dan Holmsand Date: Sat, 15 Feb 2014 11:03:24 +0100 Subject: [PATCH] First stab at ref support --- src/reagent/core.cljs | 8 +++++ src/reagent/impl/component.cljs | 6 ++-- src/reagent/impl/template.cljs | 57 ++++++++++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/src/reagent/core.cljs b/src/reagent/core.cljs index a5cf48a..0ce45e9 100644 --- a/src/reagent/core.cljs +++ b/src/reagent/core.cljs @@ -103,6 +103,14 @@ Everything is optional, except :render. [this] (.getDOMNode this)) +(defn ref [parent ref child] + (assert (util/reagent-component? parent)) + (assert (keyword? ref) (str "Ref must be a keyword, not " (pr-str ref))) + (tmpl/make-ref-component parent ref child)) + +(defn refs [this] + (assert (util/reagent-component? this)) + (tmpl/get-refs this)) (defn merge-props diff --git a/src/reagent/impl/component.cljs b/src/reagent/impl/component.cljs index 4dae8d2..425a04d 100644 --- a/src/reagent/impl/component.cljs +++ b/src/reagent/impl/component.cljs @@ -113,8 +113,10 @@ (def dont-wrap #{:cljsRender :render :componentFunction}) (defn dont-bind [f] - (doto f - (aset "__reactDontBind" true))) + (if (ifn? f) + (doto f + (aset "__reactDontBind" true)) + f)) (defn get-wrapper [key f name] (if (dont-wrap key) diff --git a/src/reagent/impl/template.cljs b/src/reagent/impl/template.cljs index 26804e4..1b91dc3 100644 --- a/src/reagent/impl/template.cljs +++ b/src/reagent/impl/template.cljs @@ -18,6 +18,7 @@ :for "htmlFor" :charset "charSet"}) + ;;; Common utilities (defn hiccup-tag? [x] @@ -47,6 +48,7 @@ (or (attr-aliases n) (util/dash-to-camel n))) + ;;; Props conversion (def cached-prop-name (memoize undash-prop-name)) @@ -84,6 +86,7 @@ (set-id-class objprops id-class)) objprops))) + ;;; Specialization for input components (defn input-initial-state [this] @@ -115,6 +118,7 @@ (def input-components #{(aget DOM "input") (aget DOM "textarea")}) + ;;; Wrapping of native components (declare as-component) @@ -150,8 +154,6 @@ (aset "componentWillReceiveProps" #(this-as C (input-will-receive-props C %))))) -;;; Conversion from Hiccup forms - (defn wrap-component [comp extras name] (let [input? (input-components comp) input-setup (if input? input-render-setup) @@ -164,6 +166,54 @@ (add-input-methods spec)) (.createClass React spec))) +(defn create-class [spec] + (comp/create-class spec as-component)) + + +;;; Ref support + +(def cljs-refs "cljsRefs") + +(defn update-ref [this] + (let [rd (-> this util/get-props :ref-data) + {:keys [parent ref]} rd + refed (-> this (aget "refs") (aget (name ref)))] + (aset parent cljs-refs + (-> (aget parent cljs-refs) + (assoc (keyword ref) refed))))) + +(def ref-component + (create-class + {:displayName "ref-component" + :component-did-mount update-ref + :component-did-update update-ref + :component-will-unmount + (fn [this] + (let [rd (-> this util/get-props :ref-data) + {:keys [parent ref]} rd + refed (-> this (aget "refs") (aget (name ref)))] + (aset parent cljs-refs + (-> (aget parent cljs-refs) + (dissoc (keyword ref)))))) + :render + (fn [this] + (let [rd (-> this util/get-props :ref-data) + {:keys [parent ref child]} rd + react-comp (as-component child)] + (-> react-comp (aget "props") (aset "ref" (name ref))) + react-comp))})) + +(defn make-ref-component [parent ref child] + [ref-component {:ref-data {:parent parent + :ref ref + :child child}}]) + +(defn get-refs [this] + (aget this cljs-refs)) + + +;;; Conversion from Hiccup forms + (defn parse-tag [hiccup-tag] (let [[tag id class] (->> hiccup-tag name (re-matches re-tag) next) comp (aget DOM tag) @@ -179,9 +229,6 @@ (def cached-wrapper (memoize get-wrapper)) -(defn create-class [spec] - (comp/create-class spec as-component)) - (defn fn-to-class [f] (let [spec (meta f) withrender (assoc spec :component-function f)