Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed wrapped inputs with non-string values & checkboxes #129

Merged
merged 2 commits into from
Aug 17, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 33 additions & 23 deletions src/sablono/interpreter.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,26 @@
;; waiting for requestAnimationFrame

#?(:cljs
(defn wrap-form-element [element]
(defn wrap-form-element [element property coerce]
(js/React.createClass
#js
{:displayName (str "wrapped-" element)
:getInitialState
(fn []
(this-as this
#js {"state_value" (aget (.-props this) "value")}))
#js {"state_value" (coerce (aget (.-props this) property))}))
:onChange
(fn [e]
(this-as this
(let [handler (aget (.-props this) "onChange")]
(when-not (nil? handler)
(handler e)
(.setState this #js {"state_value" (.. e -target -value)})))))
(.setState this #js {"state_value" (aget (.-target e) property)})))))
:componentWillReceiveProps
(fn [new-props]
(this-as this
(let [state-value (aget (.-state this) "state_value")
element (js/ReactDOM.findDOMNode this)
element-value (.-value element)]
element-value (aget (js/ReactDOM.findDOMNode this) property)]
;; on IE, onChange event might come after actual value of an element
;; have changed. We detect this and render element as-is, hoping that
;; next onChange will eventually come and bring our modifications anyways.
Expand All @@ -41,7 +40,7 @@
;; https://github.com/tonsky/rum/issues/86
(if (not= state-value element-value)
(.setState this #js {"state_value" element-value})
(.setState this #js {"state_value" (aget new-props "value")})))))
(.setState this #js {"state_value" (coerce (aget new-props property))})))))
:render
(fn []
(this-as this
Expand All @@ -50,30 +49,41 @@
(gobject/extend
element-props
(.-props this)
#js {:value (or (aget (.-state this) "state_value") js/undefined)
:onChange (aget this "onChange")
#js {:onChange (aget this "onChange")
:children (aget (.-props this) "children")})
(aset element-props property (aget (.-state this) "state_value"))
(js/React.createElement element element-props))))})))

#?(:cljs (def wrapped-input (wrap-form-element "input")))
#?(:cljs (def wrapped-select (wrap-form-element "select")))
#?(:cljs (def wrapped-textarea (wrap-form-element "textarea")))
#?(:cljs (def wrapped-input (wrap-form-element "input" "value" str)))
#?(:cljs (def wrapped-checked (wrap-form-element "input" "checked" boolean)))
#?(:cljs (def wrapped-select (wrap-form-element "select" "value" str)))
#?(:cljs (def wrapped-textarea (wrap-form-element "textarea" "value" str)))

#?(:cljs
(defn defined? [x]
(and (not (nil? x))
(not (undefined? x)))))

#?(:cljs
(defn create-element [type props & children]
(let [class (case (keyword type)
:input
(if (and props (or (exists? (.-checked props))
(exists? (.-value props))))
wrapped-input "input")
:select
(if (and props (exists? (.-value props)))
wrapped-select "select")
:textarea
(if (and props (exists? (.-value props)))
wrapped-textarea "textarea")
(name type))
(let [class (or (when (some? props)
(case (name type)
"input"
(case (.-type props)
"radio" (when (defined? (.-checked props)) wrapped-checked)
"checkbox" (when (defined? (.-checked props)) wrapped-checked)
#_else (when (defined? (.-value props)) wrapped-input))
"select" (when (defined? (.-value props)) wrapped-select)
"textarea" (when (defined? (.-value props)) wrapped-textarea)
#_else nil))
(name type))
children (remove nil? children)]
;; React does not allow for value/checked to be nil, only js/undefined
(when (some? props)
(when (nil? (.-value props))
(set! (.-value props) js/undefined))
(when (nil? (.-checked props))
(set! (.-checked props) js/undefined)))
(if (empty? children)
(js/React.createElement class props)
(apply js/React.createElement class props children)))))
Expand Down