gcanti / tcomb-form

Forms library for react
https://gcanti.github.io/tcomb-form
MIT License
1.16k stars 136 forks source link

Updating a field based on other field's selection resets all other fields #159

Closed ChristianPeters closed 9 years ago

ChristianPeters commented 9 years ago

Hi,

I built a form with tcomb-form 0.5.3 where I want to change a depending dropdown when selecting a (master) dropdown value.

I got this working with the unpleasant side-effect that all entered values of my form are reset. When selecting a project (master dropdown value), the tags dropdown (slave) is updated with the right options but the project dropdown is reset to the null option and other text fields are emptied.

EntryForm = React.createClass
  getInitialState: ->
    options:
      fields:
        tags:
          options: []
  handleChange: (value, path) ->
    return if path[0] != 'project'
    @setState options:
      fields:
        tags:
          options: projectTags[@refs.form.getComponent('project').state.value]
  render: ->
    DOM.div {},
      React.createElement(Form, ref: 'form', type: MyTCombType, options: @state.options, onChange: @handleChange)

Any idea what I'm getting wrong here? It's like I would overwrite all my values with updating the options but @setState should merge the object, right?

gcanti commented 9 years ago

Hi, You must handle also the value in the state, see this example (disable a field based on another field's value):

https://github.com/gcanti/tcomb-form/blob/master/GUIDE.md#rendering-options

ChristianPeters commented 9 years ago

Thank you for your help! This works (changes marked with **):

EntryForm = React.createClass
  getInitialState: ->
    **value: null**
    options:
      fields:
        tags:
          options: []
  handleChange: (value, path) ->
    return if path[0] != 'project'
    @setState
      **value: value**
      options:
        fields:
          tags:
            options: projectTags[@refs.form.getComponent('project').state.value]
  render: ->
    DOM.div {},
      React.createElement(Form, ref: 'form', type: MyTCombType, options: @state.options, **value: @state.value**, onChange: @handleChange)

So why does my EntryForm component have to manage its own value state? I thought this is internal data of the Form component that I can access via @refs.form.getValue() when I need it.

And why do I have to set the value when handling change although I don't want to touch it? It's not that I am using replaceState()

gcanti commented 9 years ago

Because of the re-renderings. tcomb-form behaves like the controlled components:

https://facebook.github.io/react/docs/forms.html#controlled-components