gcanti / tcomb-form

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

Add asterisk for required fields when type is dynamic #344

Closed anpr closed 8 years ago

anpr commented 8 years ago

Version

I have a form that uses a template, and the type of the form is dynamic, meaning I have different fields (which are mandatory or optional) depending on the value of another field:

// ...
let form_type_obj = {
    country: t.String,
  };

if (some_condition(this.state)) {
  form_type_obj.en_name = some_other_condition(this.state) ? t.String: t.maybe(t.String);
}

form_schema = t.struct(form_type_obj);
// ...

Problem

I want to put an asterisk after each mandatory field in the form (like it is discussed here).

const formLayout = (locals) => {
    return (
      <div>
        <div className="row">
          <div className="col-md-12">
            <div>{locals.inputs.country}</div>
          </div>
        </div>
        {some_condition(this.state) ?
        <div className="row">
          <div className="col-md-12">
            <div>{locals.inputs.en_name</div>
          </div>
        </div>: undefined
        }
      </div>
    );

How can I know at this point whether en_name is mandatory or not? Does locals somehow provide this information, e.g. locals.attributes.en_name.is_mandatory()?

I suppose I could also use some_other_condition() in the formLayout, but the actual conditions are more complex than in the example I tried to give above, so if it were possible to dynamically retrieve the type it would make my job easier :)

gcanti commented 8 years ago

Hi @anpr,

there are at least 2 ways I can think of:

t.form.Form.i18n.required = ' *'
t.form.Form.i18n.optional = ''
const Type = t.struct({
  country: t.String,
  en_name: t.maybe(t.String)
})

import classnames from 'classnames'

const myTemplate = t.form.Form.templates.textbox.clone({
  renderLabel: (locals) => {
    const className = {
      'control-label': true,
      'required': locals.typeInfo.type.meta.kind !== 'maybe' // <= and then define a .required class as in the link you posted
    }
    return <label htmlFor={locals.attrs.id} className={classnames(className)}>{locals.label}</label>
  }
})

const options = {
  fields: {
    country: { template: myTemplate },
    en_name: { template: myTemplate }
  }
}
gcanti commented 8 years ago

Closing, please reopen if you need more help

anpr commented 8 years ago

Thanks a lot this helped us and was spot-on :)