Coming from Angular, understanding scopes and how the directives/controllers interact with the HTML seem fairly logical compared with this simple example I'm trying to do.
Essentially, I have a few components.
/** @jsx React.DOM */
var React = require('react');
var {TextInput} = require("./controls/TextInput.jsx");
var Group = React.createClass({
render: function () {
console.log(this.props.formdata); // passed from parent
return (
<fieldset className="">
<legend>My Field Group</legend>
{this.props.field.fields.map(function(fld, i) {
return (<div className="my-field">
<TextInput formdata={formdata} field={fld} />
</div>);
})}
</fieldset>
);
}
});
exports.Group = Group;
My TextInput
looks like this:
** @jsx React.DOM */
var React = require('react');
var TextInput = React.createClass({
render: function () {
return (
<div className="form-group">
<label htmlFor={this._reactInternalInstance._rootNodeID+'_input'}>{this.props.field.label}</label>
<input type="" className="form-control" id={this._reactInternalInstance._rootNodeID+'_input'} value={???} placeholder=""/>
</div>
);
}
});
exports.TextInput = TextInput;
Firstly, I'm pretty sure what i'm doing with the _rootNodeId could be better, but haven't found any better examples.
My main problem is sussing out how to bind the value of the textbox to my model.
I am "using" Flux too, and have a
var SomeStore = require('../stores/some-store');
and
var SomeActions = require('../actions/some-action');
Object that I can use for managing the data and dispatching events. Essentially, what I need to happen is when a value changes in the one of the child text inputs, I want handle the change, possible change some other values in the model and tell the affected controls/dom elements to update themselves.
Any advice welcome.
Thanks Sam
I assume you want to do this without submitting actually submitting the input. In React/Flux, the stores are the closest thing you'll get to a "model". You would need to build out your Flux architecture so your React components are listening for changes to the store. For example, in your TextInput component, I'm assuming you don't want to actually submit the data (just have the information update as soon as you enter it):
** @jsx React.DOM */
var React = require('react');
var SomeActions = require('../actions/some-action');
var TextInput = React.createClass({
handleChange: function () {
var generatedRef = this._reactInternalInstance._rootNodeID+'_input';
var data = React.findDOMNode(this.refs[generatedRef]).value;
SomeActions.UpdateStore(data);
},
render: function () {
var generatedRef = this._reactInternalInstance._rootNodeID+'_input';
return (
<div className="form-group">
<label htmlFor={this._reactInternalInstance._rootNodeID+'_input'}>{this.props.field.label}</label>
<input type="text" ref={generatedRef} onChange={this.handleChange} className="form-control" id={this._reactInternalInstance._rootNodeID+'_input'} placeholder=""/>
</div>
);
}
});
exports.TextInput = TextInput;
Declaring generatedRef
isn't necessary but I did it for clarity. In SomeActions
, you'll need an to dispatch a payload through the dispatcher. SomeStore
needs to be listening for that type of payload and update its data accordingly, and then emit a change that your other components are listening for. For example:
/** @jsx React.DOM */
var React = require('react');
var {TextInput} = require("./controls/TextInput.jsx");
var SomeStore = require('../stores/some-store');
var getData = function () {
return SomeStore.retrieveData(); //should return an object
};
var Group = React.createClass({
onChange: {
this.setState(getData());
},
componentDidMount: {
SomeStore.addChangeListener(this.onChange);
},
componentWillUnmount: {
SomeStore.removeChangeListener(this.onChange);
},
render: function () {
console.log(this.props.formdata); // passed from parent
return (
<fieldset className="">
<legend>My Field Group</legend>
{this.props.field.fields.map(function(fld, i) {
return (
<div className="my-field">
<TextInput formdata={formdata} field={fld} />
</div>);
})}
</fieldset>
);
}
});
exports.Group = Group;
This is the best I can do without knowing what your actions and store look like. Basically, handleChange will dispatch an action anytime you change the data in the input field. This action will update the store. The store should emit a change
event anytime it is updated. Any component listening for those changes will then be updated accordingly to reflect the store's current data.