gcanti / tcomb-form

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

Dynamic options to Radio (t.enums) - validation error despite value selected. "Invalid value supplied to /Path" #309

Closed rajeshps closed 8 years ago

rajeshps commented 8 years ago

Version

Tell us which versions you are using:

Hi,

Am successful in creating a select from

var Gender = t.enums({
  M: 'Male',
  F: 'Female'
}, 'Gender');
var GenderFormType = t.struct({
   gender: Gender
})
<Form ref="form" type={GenderFormType} value={this.state.value} onChange={this.onChange}/>

So far good and the radio (custom template) renders perfect... also the select way works fine. Now the need is to inject the options dynamically via this.state.options and as per other issue# suggestions have done the following

  var GenderFormType = t.struct({
    gender: t.enums({})
  })
   var genderOpts = getDropdownOptions('gender');
   // the format and options structure looks like below
   // genderOpts = [{"value":"M", "text":"Male"}, {"value":"F", "text":"Female"}]
  ..................  
   var options = t.update(this.state.options, {
        fields: {
            gender: {
                options: { '$set': genderOpts }
            }
        }
    });        
    this.setState({options:options }); 
   .................

<Form ref="form" type={GenderFormType} options={this.state.options} value={this.state.value} onChange={this.onChange}/>

Select renders properly and even the default values gets in as expected. Only issue is with Validation as it always errors out saying (console output as below)

1:Struct
actual:"M"
expected: Enums(value, path)
**message: "Invalid value "M" supplied to /gender: "**
path:Array[1]

Need inputs or suggestion on how to overcome this validation limitation. Or direct me towards correct way of achieving the dynamic value for select without the validation error despite value being chosen.

Expected behavior and requirement is to have this as Radio than Select.

Thanks!

gcanti commented 8 years ago

Hi @rajeshps,

the validation fails because you are defining an empty enum:

var GenderFormType = t.struct({
  gender: t.enums({}) // <= empty enums
})

If gender values are static (i.e. just M and F) you should define:

var GenderFormType = t.struct({
  gender: t.enums.of(['M', 'F']) // <= I don't mind the labels
})

and then override the labels with your custom options (as you are already doing):

var genderOpts = getDropdownOptions('gender');
// the format and options structure looks like below
// genderOpts = [{"value":"M", "text":"Male"}, {"value":"F", "text":"Female"}]
..................  
var options = t.update(this.state.options, {
  fields: {
    gender: {
      options: { '$set': genderOpts }
    }
  }
});        
this.setState({options:options }); 

However if gender values are dynamic, you could also dynamically define the form type.

rajeshps commented 8 years ago

Thanks for the response @gcanti. Yes, gender values are dynamic, basically took gender as an example but there are other similar kind of scenarios which would require dynamic values.

You meant dynamically define field type by using factory?

However, was able to workaround this by initially setting the type to t.String and then in options to set to required type / custom type with options.

Will close this issue for now and thanks a ton for wonderful stack of libraries!