gcanti / tcomb-form

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

What's is the best way of overriding just the actual control, preserving Bootstrap's label/wrapper? #244

Closed mandx closed 8 years ago

mandx commented 8 years ago

I'm currently using a custom factory to make an Enum editable with the react-select instead of the plain select control. Works fine, but now I'm not getting the .form-group wrapper nor the .control-label. So I guess that also have to go into my factory's render method. Is there a simple way (component/class/function) already available within this library that I can use to wrap my custom control?

I just don't like the idea of copy/paste the library's code to achieve this, while maintaining the flexibility of configuring the control's layout with Forms.props.options.

gcanti commented 8 years ago

Hi @mandx,

Sorry for the delay

I'm currently using a custom factory

Should be enough using a custom template

import ReactSelect from 'react-select';

function myRenderSelect(locals) {
  const options = locals.options.filter(o => o.value).map(o => ({value: o.value, label: o.text}));
  function onChange(o) {
    locals.onChange(o ? o.value : '');
  }
  return <ReactSelect options={options} value={locals.value} onChange={onChange} />;
}

const Country = t.enums({
  IT: 'Italy',
  US: 'Unites States'
});

const Type = t.struct({
  country: Country
});

const options = {
  fields: {
    country: {
      template: myRenderSelect
    }
  }
};

Is there a simple way (component/class/function) already available within this library that I can use to wrap my custom control?

We are working on this right now:

https://github.com/gcanti/tcomb-form/issues/254

You'll be able to write something like

import ReactSelect from 'react-select';

function myRenderSelect(locals) {
  const options = locals.options.filter(o => o.value).map(o => ({value: o.value, label: o.text}));
  function onChange(o) {
    locals.onChange(o ? o.value : '');
  }
  return <ReactSelect options={options} value={locals.value} onChange={onChange} />;
}

// override just the select rendering, keep everything else
const mySelect = t.form.Form.templates.select.clone({
  renderSelect: myRenderSelect
});

const Country = t.enums({
  IT: 'Italy',
  US: 'Unites States'
});

const Type = t.struct({
  country: Country
});

const options = {
  fields: {
    country: {
      template: mySelect
    }
  }
};
mandx commented 8 years ago

Thanks for the response! Ok, so I'm closing this and start following #254.

gcanti commented 8 years ago

OK, by the way the code above works fine with the current version on master (if yout want to give it a spin)