**Table of Contents**
- [Get started](#get-started)
- [Setup](#setup)
- [Working example](#working-example)
- [API](#api)
- [`getValue()`](#getvalue)
- [`validate()`](#validate)
- [How to](#how-to)
- [Adding a default value and listening to changes](#adding-a-default-value-and-listening-to-changes)
- [Reset the form](#reset-the-form)
- [Accessing fields](#accessing-fields)
- [Submitting the form](#submitting-the-form)
- [Customised error messages](#customised-error-messages)
- [List with Dynamic Items (Different structs based on selected value)](#list-with-dynamic-items-different-structs-based-on-selected-value)
- [Types](#types)
- [Required field](#required-field)
- [Optional field](#optional-field)
- [Numbers](#numbers)
- [Refinements](#refinements)
- [Booleans](#booleans)
- [Dates](#dates)
- [Enums](#enums)
- [Lists](#lists)
- [Nested structures](#nested-structures)
- [Rendering options](#rendering-options)
- [Struct options](#struct-options)
- [Automatically generated placeholders](#automatically-generated-placeholders)
- [Fields order](#fields-order)
- [Legend](#legend)
- [Help message](#help-message)
- [Error messages](#error-messages)
- [Disabled](#disabled)
- [Fields configuration](#fields-configuration)
- [Look and feel](#look-and-feel)
- [List options](#list-options)
- [Items configuration](#items-configuration)
- [Internationalization](#internationalization)
- [Buttons configuration](#buttons-configuration)
- [Union options](#union-options)
- [Textbox options](#textbox-options)
- [Type attribute](#type-attribute)
- [Label](#label)
- [Attributes and events](#attributes-and-events)
- [Styling](#styling)
- [Checkbox options](#checkbox-options)
- [Select options](#select-options)
- [Null option](#null-option)
- [Options order](#options-order)
- [Custom options](#custom-options)
- [Render as a radio group](#render-as-a-radio-group)
- [Multiple select](#multiple-select)
- [Date options](#date-options)
- [Fields order](#fields-order-1)
- [Customizations](#customizations)
- [Templates](#templates)
- [Clone default templates](#clone-default-templates)
- [Transformers](#transformers)
- [Custom factories](#custom-factories)
- [getTcombFormFactory](#gettcombformfactory)
- [getTcombFormOptions](#gettcombformoptions)
- [Bootstrap extras](#bootstrap-extras)
- [Textbox](#textbox)
- [Addons](#addons)
- [Size](#size)
- [Select](#select)
- [Struct](#struct)
- [General configuration](#general-configuration)
- [Changing the default language](#changing-the-default-language)
- [Changing the default skin](#changing-the-default-skin)
# Get started
## Setup
```sh
$ npm install tcomb-form
```
Note: Use tcomb-form@0.6.x with react@0.13.x. See [#200](https://github.com/gcanti/tcomb-form/issues/200).
## Working example
```js
import React from 'react';
import { render } from 'react-dom';
import t from 'tcomb-form';
const Form = t.form.Form;
// define your domain model with tcomb
// https://github.com/gcanti/tcomb
const Person = t.struct({
name: t.String,
surname: t.String
});
const App = React.createClass({
save() {
// call getValue() to get the values of the form
var value = this.refs.form.getValue();
// if validation fails, value will be null
if (value) {
// value here is an instance of Person
console.log(value);
}
},
render() {
return (
);
}
});
render(, document.getElementById('app'));
```
> **Note**. Labels are automatically generated.
## API
### `getValue()`
Returns `null` if the validation failed; otherwise returns an instance of your model.
> **Note**. Calling `getValue` will cause the validation of all the fields of the form, including some side effects like highlighting the errors.
### `validate()`
Returns a `ValidationResult` (see [tcomb-validation](https://github.com/gcanti/tcomb-validation) for a reference documentation).
## How to
### Adding a default value and listening to changes
The `Form` component behaves like a [controlled component](https://facebook.github.io/react/docs/forms.html):
```js
const App = React.createClass({
getInitialState() {
return {
value: {
name: 'Giulio',
surname: 'Canti'
}
};
},
onChange(value) {
this.setState({value});
},
save() {
var value = this.refs.form.getValue();
if (value) {
console.log(value);
}
},
render() {
return (
);
}
});
```
The `onChange` handler has the following signature:
```
(raw: any, path: Array, kind?) => void
```
where
- `raw` contains the current raw value of the form (can be an invalid value for your model)
- `path` is the path to the field triggering the change
- `kind` specify the kind of change (when `undefined` means a value change)
+ `'add'` list item added
+ `'remove'` list item removed
+ `'moveUp'` list item moved up
+ `'moveDown'` list item moved down
### Reset the form
In the previous example, just pass `null` to the `value` prop:
```js
const App = React.createClass({
...
resetForm() {
this.setState({value: null});
},
save() {
var value = this.refs.form.getValue();
if (value) {
console.log(value);
// clear all fields after submit
this.resetForm();
}
},
...
});
```
### Accessing fields
You can get access to a field with the `getComponent(path)` API:
```js
const Person = t.struct({
name: t.String,
surname: t.String
});
const App = React.createClass({
onChange(value, path) {
// validate a field on every change
this.refs.form.getComponent(path).validate();
},
render() {
return (
);
}
});
```
### Submitting the form
The output of the `Form` component is a `fieldset` tag containing your fields. You can submit the form by wrapping the output with a `form` tag:
```js
const App = React.createClass({
onSubmit(evt) {
const value = this.refs.form.getValue();
if (!value) {
// there are errors, don't send the form
evt.preventDefault();
} else {
// everything ok, let the form fly...
// ...or handle the values contained in the
// `value` variable with js
}
},
render() {
return (
);
}
});
```
### Customised error messages
See [Error messages](#error-messages) section.
### List with Dynamic Items (Different structs based on selected value)
Lists of different types are not supported. This is because a `tcomb`'s list, by definition, contains only values of the same type. You can define a union though:
```js
const AccountType = t.enums.of([
'type 1',
'type 2',
'other'
], 'AccountType')
const KnownAccount = t.struct({
type: AccountType
}, 'KnownAccount')
// UnknownAccount extends KnownAccount so it owns also the type field
const UnknownAccount = KnownAccount.extend({
label: t.String,
}, 'UnknownAccount')
// the union
const Account = t.union([KnownAccount, UnknownAccount], 'Account')
// the final form type
const Type = t.list(Account)
```
Generally `tcomb`'s unions require a `dispatch` implementation in order to select the suitable type constructor for a given value and this would be the key in this use case:
```js
// if account type is 'other' return the UnknownAccount type
Account.dispatch = value => value && value.type === 'other' ? UnknownAccount : KnownAccount
```
The complete example:
```js
import React from 'react'
import t from 'tcomb-form'
const AccountType = t.enums.of([
'type 1',
'type 2',
'other'
], 'AccountType')
const KnownAccount = t.struct({
type: AccountType
}, 'KnownAccount')
const UnknownAccount = KnownAccount.extend({
label: t.String,
}, 'UnknownAccount')
const Account = t.union([KnownAccount, UnknownAccount], 'Account')
Account.dispatch = value => value && value.type === 'other' ? UnknownAccount : KnownAccount
const Type = t.list(Account)
const App = React.createClass({
onSubmit(evt) {
evt.preventDefault()
const v = this.refs.form.getValue()
if (v) {
console.log(v)
}
},
render() {
return (
)
}
})
```
# Types
Models are defined with [tcomb](https://github.com/gcanti/tcomb). tcomb is a library for Node.js and the browser which allows you to check the types of JavaScript values at runtime with a simple syntax. It's great for Domain Driven Design, for testing, and for adding safety to your internal code.
## Required field
By default fields are required:
```js
const Person = t.struct({
name: t.String, // a required string
surname: t.String // a required string
});
```
## Optional field
In order to create an optional field, wrap the field type with the `t.maybe` combinator:
```js
const Person = t.struct({
name: t.String,
surname: t.String,
email: t.maybe(t.String) // an optional string
});
```
The suffix `" (optional)"` is automatically added to optional fields.
You can customise the suffix value, or set a suffix for required fields (see the "Internationalization" section).
## Numbers
In order to create a numeric field, use the `t.Number` type:
```js
const Person = t.struct({
name: t.String,
surname: t.String,
email: t.maybe(t.String),
age: t.Number // a numeric field
});
```
tcomb-form will automatically convert numbers to / from strings.
## Refinements
A *predicate* is a function with the following signature:
```
(x: any) => boolean
```
You can refine a type with the `t.refinement(type, predicate)` combinator:
```js
// a type representing positive numbers
const Positive = t.refinement(t.Number, (n) => n >= 0});
const Person = t.struct({
name: t.String,
surname: t.String,
email: t.maybe(t.String),
age: Positive
});
```
Refinements allow you to express any custom validation with a simple predicate.
## Booleans
In order to create a boolean field, use the `t.Boolean` type:
```js
const Person = t.struct({
name: t.String,
surname: t.String,
email: t.maybe(t.String),
age: t.Number,
rememberMe: t.Boolean // a boolean field
});
```
Booleans are displayed as checkboxes.
## Dates
In order to create a date field, use the `t.Date` type:
```js
const Person = t.struct({
name: t.String,
surname: t.String,
email: t.maybe(t.String),
age: t.Number,
rememberMe: t.Boolean,
birthDate: t.Date // a date field
});
```
## Enums
In order to create an enum field, use the `t.enums` combinator:
```js
const Gender = t.enums({
M: 'Male',
F: 'Female'
});
const Person = t.struct({
name: t.String,
surname: t.String,
email: t.maybe(t.String),
age: t.Number,
rememberMe: t.Boolean,
birthDate: t.Date,
gender: Gender // enum
});
```
By default enums are displayed as selects.
## Lists
You can handle a list with the `t.list` combinator:
```js
const Person = t.struct({
name: t.String,
surname: t.String,
email: t.maybe(t.String),
age: Positive, // refinement
rememberMe: t.Boolean,
birthDate: t.Date,
gender: Gender,
tags: t.list(t.String) // a list of strings
});
```
## Nested structures
You can nest lists and structs at an arbitrary level:
```js
const Person = t.struct({
name: t.String,
surname: t.String
});
const Persons = t.list(Person);
...
```
# Rendering options
In order to customise the look and feel, use an `options` prop:
```js
```
> **Warning**. tcomb-form uses shouldComponentUpdate aggressively. In order to ensure that tcomb-form detect any change to `type`, `options` or `value` props you have to change references:
Example: disable a field based on another field's value
```js
const Type = t.struct({
disable: t.Boolean, // if true, name field will be disabled
name: t.String
});
const options = {
fields: {
name: {}
}
};
const App = React.createClass({
getInitialState() {
return {
options: options,
value: null
};
},
onSubmit(evt) {
evt.preventDefault();
var value = this.refs.form.getValue();
if (value) {
console.log(value);
}
},
onChange(value) {
// tcomb immutability helpers
// https://github.com/gcanti/tcomb/blob/master/GUIDE.md#updating-immutable-instances
var options = t.update(this.state.options, {
fields: {
name: {
disabled: {'$set': value.disable}
}
}
});
this.setState({options: options, value: value});
},
render() {
return (
);
}
});
```
## Struct options
### Automatically generated placeholders
In order to generate default placeholders use the option `auto: 'placeholders'`:
```js
const options = {
auto: 'placeholders'
};
```
Or `auto: 'none'` if you don't want neither labels nor placeholders:
```js
const options = {
auto: 'none'
};
```
### Fields order
You can sort the fields with the `order` option:
```js
const options = {
order: ['name', 'surname', 'rememberMe', 'gender', 'age', 'email']
};
```
> **Warning**: Any field that is not in this array will be omitted from the form
### Legend
You can add a fieldset legend with the `legend` option:
```js
const options = {
// you can use strings or JSX
legend: My form legend
};
```
### Help message
You can add an help message with the `help` option:
```js
const options = {
// you can use strings or JSX
help: My form help
};
```
### Error messages
You can add a custom error message with the `error` option:
```js
const options = {
error: A custom error message // use strings or JSX
};
```
`error` can also be a function with the following signature:
```
type getValidationErrorMessage = (value, path, context) => ?(string | ReactElement)
```
where
- `value` is the (parsed) current value of the component.
- `path` is the path of the value being validated
- `context` is the value of the `context` prop. Also it contains a reference to the component options.
The value returned by the function will be used as error message.
If you want to show the error message onload, add the `hasError` option:
```js
const options = {
hasError: true,
error: A custom error message
};
```
Another (advanced) way to customize the error message is to add a:
```
getValidationErrorMessage(value, path, context) => ?(string | ReactElement)
```
static function to the type, where the arguments are the same as above:
```js
const Age = t.refinement(t.Number, (n) => return n >= 18);
// if you define a getValidationErrorMessage function, it will be called on validation errors
Age.getValidationErrorMessage = (value, path, context) => {
return 'bad age, locale: ' + context.locale;
};
const Schema = t.struct({
age: Age
});
const App = React.createClass({
onSubmit(evt) {
evt.preventDefault();
const value = this.refs.form.getValue();
if (value) {
console.log(value);
}
},
render() {
return (
);
}
});
```
You can even define `getValidationErrorMessage` on the supertype in order to be DRY:
```js
t.Number.getValidationErrorMessage = (value, path, context) => {
return 'bad number';
};
Age.getValidationErrorMessage = (value, path, context) => {
return 'bad age, locale: ' + context.locale;
};
```
### Disabled
You can disable the whole fieldset with the `disabled` option:
```js
const options = {
disabled: true
};
```
### Fields configuration
You can configure each field with the `fields` option:
```js
const options = {
fields: {
name: {
// name field configuration here..
},
surname: {
// surname field configuration here..
},
...
}
});
```
`fields` is a hash containing a key for each field you want to configure.
### Look and feel
You can customise the look and feel with the `template` option:
```js
const options = {
template: mytemplate // see Templates section for documentation
}
```
## List options
The following options are similar to the Struct ones:
- `auto`
- `disabled`
- `help`
- `hasError`
- `error`
- `legend`
- `template`
### Items configuration
To configure all the items in a list, set the `item` option:
```js
const Colors = t.list(t.String);
const options = {
item: {
type: 'color' // HTML5 type attribute
}
});
```
### Internationalization
You can override the default language (english) with the `i18n` option:
```js
const options = {
i18n: {
add: 'Nuovo', // add button
down: 'Giù', // move down button
optional: ' (opzionale)', // suffix added to optional fields
required: '', // suffix added to required fields
remove: 'Elimina', // remove button
up: 'Su' // move up button
}
};
```
### Buttons configuration
You can prevent operations on lists with the following options:
- `disableAdd`: (default `false`) prevents adding new items
- `disableRemove`: (default `false`) prevents removing existing items
- `disableOrder`: (default `false`) prevents sorting existing items
```js
const options = {
disableOrder: true
};
```
## Union options
```js
const AccountType = t.enums.of([
'type 1',
'type 2',
'other'
], 'AccountType')
const KnownAccount = t.struct({
type: AccountType
}, 'KnownAccount')
// UnknownAccount extends KnownAccount so it owns also the type field
const UnknownAccount = KnownAccount.extend({
label: t.String,
}, 'UnknownAccount')
// the union
const Account = t.union([KnownAccount, UnknownAccount], 'Account')
// the final form type
const Type = t.list(Account)
const options = {
item: [ // one options object for each concrete type of the union
{
label: 'KnownAccount'
},
{
label: 'UnknownAccount'
}
]
}
```
## Textbox options
> **Tech note**. Values containing only white spaces are converted to null.
The following options are similar to the fieldset ones:
- `disabled`
- `help`
- `hasError`
- `error`
- `template`
### Type attribute
You can set the type attribute with the `type` option. The following values are allowed:
- 'text' (default)
- 'password'
- 'hidden'
- 'textarea' (outputs a textarea instead of a textbox)
- 'static' (outputs a static value)
- all the HTML5 type values
### Label
You can override the default label with the `label` option:
```js
const options = {
fields: {
name: {
// you can use strings or JSX
label: My label
}
}
};
```
### Attributes and events
You can add attributes and events with the `attrs` option:
```js
const options = {
fields: {
name: {
attrs: {
autoFocus: true,
placeholder: 'Type your name here',
onBlur: () => {
console.log('onBlur');
}
}
}
}
};
```
### Styling
You can a style class with the `className` or the `style` attribute:
```js
const options = {
fields: {
name: {
attrs: {
className: 'myClassName'
}
}
}
};
```
`className` can be a string, an array of strings or a dictionary `string -> boolean`.
## Checkbox options
The following options are similar to the textbox ones:
- `attrs`
- `label`
- `help`
- `disabled`
- `hasError`
- `error`
- `template`
## Select options
The following options are similar to the textbox ones:
- `attrs`
- `label`
- `help`
- `disabled`
- `hasError`
- `error`
- `template`
### Null option
You can customise the null option with the `nullOption` option:
```js
const options = {
fields: {
gender: {
nullOption: {value: '', text: 'Choose your gender'}
}
}
};
```
You can remove the null option by setting the `nullOption` option to `false`.
> **Warning**: when you set `nullOption = false` you must also set the Form's `value` prop for the select field.
> **Tech note**. A value equal to `nullOption.value` (default `''`) is converted to `null`.
### Options order
You can sort the options with the `order` option:
```js
const options = {
fields: {
gender: {
order: 'asc' // or 'desc'
}
}
};
```
### Custom options
You can customise the options with the `options` option:
```js
const options = {
fields: {
gender: {
options: [
{value: 'M', text: 'Maschio'},
// use `disabled: true` to disable an option
{value: 'F', text: 'Femmina', disabled: true}
]
}
}
};
```
An option is an object with the following structure:
```js
{
value: string, // required
text: string, // required
disabled: ?boolean // optional, default = false
}
```
You can also add optgroups:
```js
const Car = t.enums.of('Audi Chrysler Ford Renault Peugeot');
const Select = t.struct({
car: Car
});
const options = {
fields: {
car: {
options: [
{value: 'Audi', text: 'Audi'}, // an option
{label: 'US', options: [ // a group of options
{value: 'Chrysler', text: 'Chrysler'},
{value: 'Ford', text: 'Ford'}
]},
{label: 'France', options: [ // another group of options
{value: 'Renault', text: 'Renault'},
{value: 'Peugeot', text: 'Peugeot'}
], disabled: true} // use `disabled: true` to disable an optgroup
]
}
}
};
```
### Render as a radio group
You can render the select as a radio group by using the `factory` option to override the default:
```js
const options = {
factory: t.form.Radio
};
```
### Multiple select
You can turn the select into a multiple select by passing a `list` as type and using the `factory` option to override the default:
```js
const Car = t.enums.of('Audi Chrysler Ford Renault Peugeot');
const Select = t.struct({
car: t.list(Car)
});
const options = {
fields: {
car: {
factory: t.form.Select
}
}
};
```
## Date options
The following options are similar to the textbox ones:
- `label`
- `help`
- `disabled`
- `hasError`
- `error`
- `template`
### Fields order
You can sort the fields with the `order` option:
```js
const Type = t.struct({
date: t.Date
});
const options = {
fields: {
date: {
order: ['D', 'M', 'YY']
}
}
};
```
# Customizations
## Templates
To customise the "skin" of tcomb-form you have to write a *template*. A template is simply a function with the following signature:
```
(locals: any) => ReactElement
```
where `locals` is an object contaning the "recipe" for rendering the input, and is built by tcomb-form for you.
For example, this is the recipe for a textbox:
```js
{
attrs: Object // should render attributes and events
config: Object // custom options, see Template addons section
context: Any // a reference to the context prop
disabled: maybe(Boolean), // should be disabled
error: maybe(Label), // should show an error
hasError: maybe(Boolean), // if true should show an error state
help: maybe(Label), // should show a help message
label: maybe(Label), // should show a label
onChange: Function, // should call this function with the changed value
path: Array, // the path of this field with respect to the form root
type: String, // should use this as type attribute
typeInfo: Object // an object containing info on the current type
value: Any // the current value of the textbox
}
```
You can set a custom template using the `template` option:
```js
const Animal = t.enums({
dog: "Dog",
cat: "Cat"
});
const Pet = t.struct({
name: t.String,
type: Animal
});
const Person = t.struct({
name: t.String,
pets: t.list(Pet)
});
const formLayout = (locals) => {
return (
formLayout
{locals.inputs.name}
{locals.inputs.pets}
);
};
const petLayout = (locals) => {
return (
petLayout
{locals.inputs.name}
{locals.inputs.type}
);
};
const options = {
template: formLayout,
fields: {
pets: { // <- pets is a list, you can customise the elements with the `item` option
item: {
template: petLayout
}
}
}
};
const value = {
name: 'myname',
pets: [
{name: 'pet1', type: 'dog'},
{name: 'pet2', type: 'cat'}
]
};
const App = React.createClass({
save() {
const value = this.refs.form.getValue();
if (value) {
console.log(value);
}
},
render() {
return (
);
}
});
```
### Clone default templates
In order to keep the majority of the implementation a template can be cloned. Every template own a series of `render*` function that can be overridden:
```js
const Type = t.struct({
name: t.String
})
const myTemplate = t.form.Form.templates.textbox.clone({
// override just the input default implementation (labels, help, error will be preserved)
renderInput: (locals) => {
return
}
})
const options = {
fields: {
name: {
template: myTemplate
}
}
}
```
## Transformers
Say you want a search textbox which accepts a list of keywords separated by spaces:
```js
const Search = t.struct({
search: t.list(t.String)
});
```
tcomb-form by default will render the `search` field as a list. In order to render a textbox you have to override the default behaviour with the `factory` option:
```js
const options = {
fields: {
search: {
factory: t.form.Textbox
}
}
};
```
There is a problem though: a textbox handles only strings, so we need a way to transform a list to a string and a string to a list. A `Transformer` deals with serialization / deserialization of data and has the following interface:
```js
const Transformer = t.struct({
format: t.Function, // from value to string, it must be idempotent
parse: t.Function // from string to value
});
```
**Important**. the `format` function SHOULD BE idempotent.
A basic transformer implementation for the search textbox:
```js
const listTransformer = {
format: (value) => {
return Array.isArray(value) ? value.join(' ') : value;
},
parse: (str) => {
return str ? str.split(' ') : [];
}
};
```
Now you can handle lists using the transformer option:
```js
// example of initial value
const value = {
search: ['climbing', 'yosemite']
};
const options = {
fields: {
search: {
factory: t.form.Textbox,
transformer: listTransformer,
help: 'Keywords are separated by spaces'
}
}
};
```
## Custom factories
The easisiest way to define a custom factory is to extend `t.form.Component` and define the `getTemplate` method:
```js
//
// a custom factory representing a tags input
//
import React from 'react';
import t from 'tcomb-form';
import TagsInput from 'react-tagsinput'; // I'm using this but you can build your own (and reusable!) tagsinput
class TagsComponent extends t.form.Component { // extend the base class
getTemplate() {
return (locals) => {
return (
);
};
}
}
export default TagsComponent;
```
Usage
```js
const Type = t.struct({
tags: t.list(t.String)
});
const options = {
fields: {
tags: {
factory: TagsComponent
}
}
};
const value = {
tags: [] // react-tagsinput requires an initial value
}
...
```
## getTcombFormFactory
If a type owns a `getTcombFormFactory(options)` static function, it will be used to retrieve the suitable factory
**Example**
```js
// instead of
const Country = t.enums.of(['IT', 'US'], 'Country');
const Type = t.struct({
country: Country
});
const options = {
fields: {
country: {
factory: t.form.Radio
}
}
};
// you can write
const Country = t.enums.of(['IT', 'US'], 'Country');
Country.getTcombFormFactory = (/*options*/) => {
return t.form.Radio;
};
const Type = t.struct({
country: Country
});
const options = {};
```
## getTcombFormOptions
If a type owns a `getTcombFormOptions` static function, tcomb-form will call it and use the result to populate the rendering options.
For example, the following two code snippets behave the same:
```js
const Message = t.maybe(t.String);
const Textbox = t.struct({
message: Message
});
Message.getTcombFormOptions = formOptions => ({
help: Enter text here!
});
```
```js
const Textbox = t.struct({
message: t.maybe(t.String)
});
const options = {
fields: {
message: {
help: Enter text here!
}
}
};
```
You can mix and match `Form`'s `options` prop and `getTcombFormOptions` as you see fit. The `formOptions` parameter passed to `getTcombFormOptions` contains the rendering options for this type as passed in via `Form`'s `options` prop, if any.
`getTcombFormOptions` is particularly helpful to keep code easy to follow when using tcomb-form on deeply nested data structures.
# Bootstrap extras
## Textbox
### Addons
You can set an addon before or an addon after with the `config.addonBefore` and `config.addonAfter` options:
```js
const Textbox = t.struct({
mytext: t.String
});
const options = {
fields: {
mytext: {
config: {
// you can use strings or JSX
addonBefore: before,
addonAfter: after
}
}
}
};
```
You can set a button after (before) with the `config.buttonAfter` (`config.buttonBefore`) option:
```js
const options = {
fields: {
mytext: {
config: {
buttonAfter:
}
}
}
};
```
### Size
You can set the textbox size with the `config.size` option:
```js
const Textbox = t.struct({
mytext: t.String
});
const options = {
fields: {
mytext: {
config: {
size: 'lg' // xs sm md lg are allowed
}
}
}
};
```
## Select
Same as Textbox extras.
## Struct
You can render the form horizontal with the `config.horizontal` option:
```js
const Person = t.struct({
name: t.String,
notifyMe: t.Boolean,
email: t.maybe(t.String)
});
const options = {
config: {
// for each of lg md sm xs you can specify the columns width
horizontal: {
md: [3, 9],
sm: [6, 6]
}
}
};
// remember to add the proper bootstrap style class
// to a wrapping div (or form) tag in order
// to get a nice layout
```
# General configuration
tcomb-form uses the following default settings:
- English as language
- Bootstrap as theme ([tcomb-form-templates-bootstrap](https://github.com/gcanti/tcomb-form-templates-bootstrap))
## Changing the default language
```js
import t from 'tcomb-form/lib'; // load tcomb-form without templates and i18n
import templates from 'tcomb-form-templates-bootstrap';
t.form.Form.templates = templates;
t.form.Form.i18n = {
optional: ' (opzionale)',
required: '',
add: 'Nuovo',
remove: 'Elimina',
up: 'Su',
down: 'Giù'
};
```
Or pick one in the `i18n` folder (constributions welcome!):
```js
import t from 'tcomb-form/lib'; // load tcomb-form without templates and i18n
import templates from 'tcomb-form-templates-bootstrap';
import i18n from 'tcomb-form/lib/i18n/it';
t.form.Form.templates = templates;
t.form.Form.i18n = i18n;
```
## Changing the default skin
```js
import t from 'tcomb-form/lib'; // load tcomb-form without templates and i18n
import i18n from 'tcomb-form/lib/i18n/en';
import semantic from 'tcomb-form-templates-semantic';
t.form.Form.i18n = i18n;
t.form.Form.templates = semantic;
```