reagent-project / reagent-forms

Bootstrap form components for Reagent
339 stars 78 forks source link

Examples of work with the generated fields #9

Closed zcho closed 9 years ago

zcho commented 9 years ago

It would be great to see examples of work with the generated fields like date of birth (number of days in February may vary depending on the year) screen shot 2014-09-15 at 21 13 16

yogthos commented 9 years ago

Good idea, you should be able to group the fields using the :id key. With the latest version if you do the following:

[:select {:field :single-select :id :dob.day
  [:option {:key :1} 1]
  ...]
[:select {:field :single-select :id :dob.month
  [:option {:key :january} "January"]
  ...]
[:select {:field :single-select :id :dob.year
  [:option {:key :1996} "1996"]
  ...]

Then the fields should be populated in the document under:

{:dob {:year :1996 :month :january :day :1} }

At the moment the :key should point to a keyword, but that could be changed if it's too restrictive.

zcho commented 9 years ago

Thank you. What should I do if I want to dynamically generate/change options for :select ? like:

(defn day-input [name year month]
  (let [date (js/Date. year month 0)
        days-in-month (.getDate date)]
  [:select.form-control {:field :list :id (keyword name)}
   (for [i (range 1 days-in-month)]
     [:option {:key (keyword i)} i])]
))
yogthos commented 9 years ago

Looks like I actually got it wrong above since you have to use :list for the select type, here's a working example:

(def months
  ["January" "February" "March" "April" "May" "June" "July" "August" "September" "October" "November" "December"])

(def dob-form
  [:select {:field :list :id :dob.day}
      (for [i (range 1 32)]
        [:option {:key (keyword i)} i])]
     [:select {:field :list :id :dob.month}
      (for [month months]
        [:option {:key (keyword month)} month])]
     [:select {:field :list :id :dob.year}
      (for [i (range 1950 (inc (.getFullYear (js/Date.))))]
        [:option {:key (keyword i)} i])])
zcho commented 9 years ago

There are the following problem: The number of days should depend on the month and year (leap year or not)

yogthos commented 9 years ago

You'd have to add extra logic for handling that, but the form binding will stay the same. It might make sense to make this a default form element like :date-select or something.

zcho commented 9 years ago

Thank you. But how to make two fields connected and dynamically change the number of options in select?

yogthos commented 9 years ago

Come to think of it, that's a bit tricky at the moment, since I bind the fields from the template before it's run, you can't really change the number of elements after the fact. One option could be to add a :visible? key that could point to a test function that decides whether it should be shown or not.

I'm thinking something like this:

[:select {:field :list :id :dob.day}
      (for [i (range 1 32)]
        [:option
         {:key (keyword (str i))
          :visible? #(let [month (get-in % [:dob :month])]
                       (cond
                        (< i 29) true
                        (= i 30)
                        (not= month "February")
                        (= i 31)
                        (some #{month} ["January" "March" "May" "July" "August" "October" "December"])
                        :else false))}
         i])]
yogthos commented 9 years ago

Ok, so I've got the above implemented, let me know if it works as expected:

(def months
  ["January" "February" "March" "April" "May" "June" "July" "August" "September" "October" "November" "December"])

[:select {:field :list :id :dob.day}
      (for [i (range 1 32)]
        [:option
         {:key (keyword (str i))
          :visible? #(let [month (get-in % [:dob :month])]
                       (cond
                        (< i 29) true
                        (= i 30)
                        (not= month "February")
                        (= i 31)
                        (some #{month} ["January" "March" "May" "July" "August" "October" "December"])
                        :else false))}
         i])]
   [:select {:field :list :id :dob.month}
      (for [month months]
        [:option {:key (keyword month)} month])]
   [:select {:field :list :id :dob.year}
      (for [i (range 1950 (inc (.getFullYear (js/Date.))))]
        [:option {:key (keyword (str i))} i])]
zcho commented 9 years ago

Thanks!

Select control is not synchronized with the Reagent atom ([reagent-forms "0.2.0"]).

some code:

[:select {:field :list :id :sample}
  [:option {:key :1} "1"]
  [:option {:key :2} "2"]
]

populate with:

{:sample "2"}

attempted and so

{:sample :2}

Control remains in the initial state.

yogthos commented 9 years ago

Good catch, I'm not setting the "selected" attribute for the option when the form loads. I'll have a fix shortly.

yogthos commented 9 years ago

should be fixed in [0.2.1]

zcho commented 9 years ago

yes, fixed, Thanks!