Closed jfeltesse closed 9 years ago
Hi! See the issues labelled with "dynamic forms":
In particular for dynamic selects:
https://github.com/gcanti/tcomb-form/issues/78
You can even modify the type on the fly:
Thanks for the pointers.
I got it to work but for the life of me I can't get it to play nice with existing options like config
and i18n
.
Basically, the config and i18n options work but only for that field, after that they're gone OR they work but the dropdown is not populated.
import React from 'react';
import Tcomb from 'tcomb-form';
let Form = Tcomb.form.Form;
let Contact = Tcomb.struct({
civilite: Tcomb.maybe(Tcomb.enums({})),
nom: Tcomb.Str,
prenom: Tcomb.maybe(Tcomb.Str)
});
let options = {
i18n: {
add: 'Nouveau',
down: '↓',
optional: ' (facultatif)',
remove: 'Supprimer',
up: '↑'
},
config: {
horizontal: {
sm: [2, 10]
}
}
}
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.state = { };
}
componentDidMount() {
fetchFormDropdowns().then((dropdowns) => {
options.fields = {
civilite: {
factory: Tcomb.form.Select,
options: dropdowns.civilites
}
};
this.setState({ options: options });
});
}
render() {
return (
<div className="contact_form">
<h1>Nouveau contact</h1>
<Form ref="form" type={Contact} options={this.state.options} />
</div>
);
}
}
makes such a form (with the select dropdown populated properly):
As you can see the layout and i18n settings work on the first field but are "forgotten" for the others.
Setting the initial state like this.state = { options: options };
in the constructor makes a form like the screenshot below but in that case the select dropdown is not populated...
Ah!
Obviously moments after I wrote this reply I notice issue #128 which deals with that case.
For reference to the people stumbling here, I got it to work with the following:
let options = {
// options from above plus
fields: {
civilite: { }
}
}
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.state = { options: options };
}
componentDidMount() {
fetchFormDropdowns().then((dropdowns) => {
let newOptions = Tcomb.update(this.state.options, {
fields: {
civilite: {
options: { '$set': dropdowns.civilites }
}
}
});
this.setState({ options: newOptions });
});
}
// rest of the code above
}
Thanks for the help!!
Thanks for the help!!
De rien.
Just a few remarks:
1) you can set the i18n
option globally in order to be DRY (I guess you want the french localization in all your forms):
// this will be used for all the forms
// you can still override this global setting in a local form options
// if you need
Form.i18n = {
add: 'Nouveau',
down: '↓',
optional: ' (facultatif)',
remove: 'Supprimer',
up: '↑'
};
...
let options = {
config: {
horizontal: {
sm: [2, 10]
}
}
};
// instead of
let options = {
i18n: {
add: 'Nouveau',
down: '↓',
optional: ' (facultatif)',
remove: 'Supprimer',
up: '↑'
},
config: {
horizontal: {
sm: [2, 10]
}
}
}
2) add the bootstrap form-horizontal
className to your wrapping div in order to get a nice layout:
render() {
return (
<div className="contact_form form-horizontal"> // <-- here
<h1>Nouveau contact</h1>
<Form ref="form" type={Contact} options={this.state.options} />
</div>
);
}
3) Tcomb.form.Select
is the default for enums:
civilite: {
factory: Tcomb.form.Select, // <-- you can safely remove this
options: dropdowns.civilites
}
Hi,
React & tcomb beginner here so bear with me please.
Going through the doc and issues here I couldn't find how to dynamically build enums in a form. My use case being that I want to make a contact form where the user chooses its title (Mr, Ms etc.). These are values defined in a remote DB's table, hence the dynamic loading.
The doc has this sort of example (trimmed):
but it's static.
I suppose I could modify the
Person
struct (to follow that example) in the constructor function of the component (using ES6,getInitialState
is gone) but the doc is not very clear about how to dynamically modify a struct.