reagent-project / reagent-forms

Bootstrap form components for Reagent
339 stars 78 forks source link

Component State #137

Open njj opened 6 years ago

njj commented 6 years ago

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}]]]))
yogthos commented 6 years ago

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.

njj commented 6 years ago

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

yogthos commented 6 years ago

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.

njj commented 6 years ago

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

yogthos commented 6 years ago

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

njj commented 6 years ago

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

nenadalm commented 6 years ago

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?

yogthos commented 6 years ago

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