reagent-project / reagent-forms

Bootstrap form components for Reagent
339 stars 78 forks source link

Issue with atoms inside of the form #39

Closed gdulus closed 9 years ago

gdulus commented 9 years ago

Hey

First of all, great job. I really like you project. But i have small problem. I'm new to reagent/react so maybe its just a newbee mistake. I have such code (simplified):

(def ^:private form-data (r/atom {}))
(def ^:private submiting (r/atom false))

(defn- form-submit-handler []
  (do
    (reset! submiting true)
    (POST "/post" {:params (str @form-data)})))

(defn- input-field [id type label help]
  [:label {:for id} label
   [:div.input-group
    [:input.form-control {:field type :id id}]
    [:div.input-group-addon
     [:span.glyphicon.glyphicon-info-sign {:data-content help :data-placement :left}]]]])

(def ^:private form-template
  [:form
   (input-field :name :text "User name" "...")
   (input-field :name :text "User password" "...")
   [:div.form-group
    [:div.buttons {:class (str @submiting)}
     (if @submiting
       [:span.loader.pull-right]
       [:span.btn.btn-default.pull-right {:on-click form-submit-handler} "Save"])
     ]]])

(defn presenter []
  (fn []
    [:div.row {:id "register"}
      [:h2.text-center "Header"]]
     [:div.col-md-12
      [bind-fields form-template form-data]]]))

When "Save" button is clicked, "submiting" atom is set to true and button should disappear. But it doesn't work. It works when i move buttons markup and logic from form-template variable to presenter function. Is it as it should be?

yogthos commented 9 years ago

The template can't reference external variables such as submitting atom directly. However, you could use a separate component for the button as seen below. Also, only the last returned by returned by the presenter function will be used, so its content needs to be inside a div. Finally, you'd probably want to reset submitter to false any time you have input in the form, this can be done using an event as seen below. Hope this helps.

(def ^:private form-data (atom {}))
(def ^:private submiting (atom false))

(defn- form-submit-handler []
  (swap! submiting not))

(defn- input-field [id type label help]
  [:label {:for id} label
   [:div.input-group
    [:input.form-control {:field type :id id}]
    [:div.input-group-addon
     [:span.glyphicon.glyphicon-info-sign {:data-content help :data-placement :left}]]]])

(defn submit-button []
  [:div.buttons {:class (str @submiting)}
     (if @submiting
       [:span.loader.pull-right]
       [:span.btn.btn-default.pull-right {:on-click form-submit-handler} "Save"])])

(def ^:private form-template
  [:form
   (input-field :name :text "User name" "...")
   (input-field :name :text "User password" "...")
   [:div.form-group [submit-button]]])

(defn presenter []
  (fn []
    [:div
     [:div.row {:id "register"}
      [:h2.text-center "Header"]]
     [:div.col-md-12
      [bind-fields form-template form-data
       (fn [_ _ _] (reset! submiting false))]]]))