Search code examples
clojurescriptre-frame

changing db value in input form in reframe


I've been trouble by an updating issue in reframe.

db.cljs:

{:apple 16}

event.cljs

(rf/reg-event-db
:update-apple-size
  (fn [ db [_ size] ]
    (assoc db :apple size)))

subs.cljs

(rf/reg-subs
 ::apple-size
 (fn [ db ]
    (get db :apple))) 

views.cljs

[:input {:type :text
         :on-change (rf/dispatch [:update-apple-size (.. % -target -value js/parseFloat))]
         :value @(rf/subscribe [::apple-size] }]

The issue happed when user udpating with decimal number of the size. When user try to update current 16 to 16.5.

User will strike . ,but this will be trigger on-change event and wont' update the db value. ( {:apple 16} => {:apple 16.0} ) ?. Then the subscribe will render "16.0" to UI as "16" ?

that's why user can't really append decimals after an integer in input element ?

  • one way I can think of is stringyfy all values in db but this will create lots of trouble since there are lots of calculation assuming the values are number in the db.

Any advise will be helpful !


Solution

  • Note that js/parseFloat parses a string with a decimal dot into an integer:

    cljs.user=> (js/parseFloat "16.")
    16
    

    One solution can be to save into db two values:

    • the value of input as a string
    • the parsed value of input

    Then input will display a string with a decimal dot. See example:

    Db:

    (def default-db
      {:input-val "5"
       :input-num 5})
    

    Views:

     [:input {:type "string"
                         :value @(re-frame/subscribe [::subs/input-val])
                         :on-change #(re-frame.core/dispatch [:change-val (-> % .-target .-value)])}]
                [:div
                 [:p @(re-frame/subscribe [::subs/input-num])]]
    

    Subs:

    (re-frame/reg-sub
      ::input-val
      (fn [db] (:input-val db)))
    
    (re-frame/reg-sub
      ::input-num
      (fn [db] (:input-num db)))
    

    Events:

    (re-frame/reg-event-db
      :change-val
      (fn [db [_ val]]
          (-> db
              (assoc :input-val val)
              (assoc :input-num (js/parseFloat val)))))