I'm trying to make a simple form system for a project I'm working on, and the idea is simple. I have a FormStore
where forms can be registered, components can be registered to those forms and all the data can be retrieved.
I want to make this as automated as possible, so when the <Form>
element is mounted, it should search any children for a isFormItem
property, and automatically register that input field with some callback to get the values, defined within the input element.
The issue I'm facing is that I don't know how I would access the child component from the higher level component. I don't think there's a way to use refs, since those have to be manually assigned, and that's what I'm trying to avoid.
This is the relevant snippet from my Form.react.jsx. This is where I try to attach each Input field to the form.
componentDidMount() {
const name = this.props.name ||
'form_' + Math.floor(Math.random() * 100000000);
FormStore.registerForm(name);
React.Children.forEach(this.props.children, (child) => {
if (selectn('props.isFormItem', child)) {
// I need to call child.attachToForm somehow...
}
});
};
And these are the relevant parts of Input.react.jsx.
constructor(props) {
this.attachToForm = this.attachToForm.bind(this);
}
attachToForm(formName) {
const name = this.props.name ||
'formItem_' + Math.floor(Math.random() * 100000000);
FormStore.attachToForm(formName, name, () => this.state.value);
}
I have tried accessing the child component method like this:
React.Children.forEach(this.props.children, (child) => {
if (selectn('props.isFormItem', child)) {
child.type.prototype.attachToForm =
child.type.prototype.attachToForm.bind(child);
child.type.prototype.attachToForm(name);
}
});
But calling the prototype doesn't bind the actual object instance anywhere, so that ended up in having a whole bunch of binds everywhere, and in the end it didn't evne work in addition to being terribly messy all around.
Is there some way of doing this? I am just not seeing it... Any help would be appreciated.
You can pass the formName
as a prop to each Input
component and then attach each item in it‘s own componentDidMount
method instead.
Also, the getDefaultProps
method seems handy in your case.
Something like:
getDefaultProps() {
return {
name: 'form_' + Math.floor(Math.random() * 100000000)
}
}
render() {
return <Input formName={this.props.name} />
}
And then in the Input component:
getDefaultProps() {
return {
name: 'formItem_' + Math.floor(Math.random() * 100000000)
}
}
componentDidMount() {
FormStore.attachToForm(this.props.formName, this.props.name, () => this.state.value)
}