reagent-forms icon indicating copy to clipboard operation
reagent-forms copied to clipboard

Component State

Open njj opened this issue 6 years ago • 8 comments

Hey there! I'm trying to track the state change of an input to apply various CSS classes to it based on valid/invalid state.

For some reason it doesn't seem like the input is being re-rendered after I update component state on blur when I'm using () to implement the inputs. Strangely enough, I can see the event firing via console log when I render the input as [] but the actual state updating still does not happen.

Here's a snippet, ignore some of the random stuff in there. The key piece here is the swap! on-blur:

(defn input [label type id error-id]
  (let [key (keyword (name id))
        component-state (r/atom {:count 0})]
    (js/console.log "hi" label (get @component-state :count))
   [:div.col-sm-6
    [:label.input-label label]
    [:div.input-container
     [:input.input-field.form-control
      {:field type
       :id id
       :on-blur #(swap! component-state update-in [:count] inc)}]
     [:div.error-container {:field :alert :id error-id}]]]))

njj avatar Mar 12 '18 15:03 njj

The form definition has to be a data structure, and it's not possible to put in functions because bind-fields users postwalk to walk the structure and create UI components from it. The fields inside your input will never be processed by the library. There's a bit more on this in the binding the form to a document section.

yogthos avatar Mar 12 '18 18:03 yogthos

@yogthos Thanks for the reply. How might you recommend we approach something like this? Basically the scenario is we want to conditionally apply a CSS class to inputs based on if they are errored out or not.

njj avatar Mar 12 '18 18:03 njj

Unfortunately, that's a bit of an omission at the moment. The only field that allows setting class on validation is :container, so you can do something like:

[:span {:field :container :valid? #(when (empty? (:first-name %)) "error")}
 [:input {:field :text :id :first-name}]]

I'll take a look at extending this for all field types.

yogthos avatar Mar 12 '18 19:03 yogthos

@yogthos Thanks! I think this will work as a stop gap.

njj avatar Mar 12 '18 19:03 njj

I'll keep this open actually, since it does look like something that would be good to add.

yogthos avatar Mar 12 '18 19:03 yogthos

@yogthos Maybe if I find the time, I can try and make a PR soon.

njj avatar Mar 12 '18 19:03 njj

Hi. I wanted to try this library with material-ui.

Material-ui has component TextField, which can be used instead of :input and data flows flawlessly. The problem is with validation. TextField has prop error which should be set to true if error occurs (so the input is red) and prop helperText to which error message can be put.

Based on the docs, it doesn't seems to be currently possible. Maybe additional prop could be added into reagent-forms (:on-document-change?) Which could accept callback that can alter props of the :input and read the document?

nenadalm avatar Mar 12 '18 20:03 nenadalm

Yeah, I think having a general function that can modify the attributes would be very useful.

yogthos avatar Mar 12 '18 20:03 yogthos