-
Notifications
You must be signed in to change notification settings - Fork 2
Form Usage
Generally, you can use form's $
method when rendering your inputs. This method generates a set of properties that are consumed by input components.
class UserForm extends Form {
render() {
return (
<div>
<TextField {...this.$('firstName')} />
<TextField {...this.$('lastName')} />
<button onClick={this.save.bind(this)}>Save</button>
</div>
);
}
}
Form's $
method accepts a string as an argument. This string represents input name - a dot-separated value that specifies input's nesting and/or position in collection. For example, 'address.city'
, 'favoriteLanguages.1'
, 'items.0.amount'
are all valid input names. Form example bellow deals with address object nested under address
property of it's attrs
.
class RegistrationForm extends Form {
render() {
return (
<div>
<TextField {...this.$('email')} />
<Select {...this.$('address.country')} options={countries} />
<TextField {...this.$('address.city')} />
<TextField {...this.$('address.streetLine')} />
<button onClick={this.save.bind(this)}>Save</button>
</div>
);
}
}
Custom onChange
handler is passed in additional parenthesis after $
function call. It's first argument is handler itself, and subsequent values are bound to handler function call.
class OrderForm extends Form {
changeItem(value) {
this.set({
item: value,
amount: null
});
}
render() {
return (
<div>
<Select {...this.$('item')(this.changeItem)} options={['Item 1', 'Item 2']} />
<Select {...this.$('amount')} options={['10', '50', '100']} />
<button onClick={this.save.bind(this)}>Save</button>
</div>
);
}
}
If you don't have extra logic based on render method (such as implementing
rendering in base form and calling super.render(someContent)
from child
forms), and you want to make things a little bit more DRY, you may declare
your form's rendering using $render
method that accepts input-generation
function as argument. Thus, removing the this.
prefix in inputs:
class UserForm extends Form {
$render($) {
return (
<div>
<TextField {...$('firstName')} />
<TextField {...$('lastName')} />
<TextField {...$('email')} />
</div>
);
}
}
This form of rendering declaration is also very useful when working with
nested forms, since it has a special nested
method that will generate
onChange handler for nested form for you:
{this.map('items', (_item, i) =>
<ItemForm key={i} {...$.nested(`items.${i}`)} />
)}
Of course, since $
is argument in this method, you may use any name for
this variable that you find suitable.
If your form is small enough, you might want to render it inline instead of
defining separate form component. In this case you may pass renderer function
as only form's child. This function takes form's $
function as argument for
convenience. Note that you still need to define static validation
rules
for the Form to be able to use validations.
<Form {...bindState(this)} validations={{ email: ['presence', 'email'], fullName: 'presence' }}>
{$ => (
<div>
<TextField {...$('email')} label="Email" />
<TextField {...$('fullName')} label="FullName" />
<button onClick={this.registerUser}>Register</button>
</div>
)}
</Form>