 ;; 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.

              (gobject/extend
                element-props
                (.-props this)
                #js {:value    (or (aget (.-state this) "state_value") js/undefined)
                     :onChange (aget this "onChange")
                     :children (aget (.-props this) "children")})
              (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
   (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))
           children (remove nil? children)]
       (if (empty? children)
         (js/React.createElement class props)
         (apply js/React.createElement class props children)))))

              ;; 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" (coerce (aget new-props property))})))))
        :render
        (fn []
          (this-as this
