Skip to content

Instantly share code, notes, and snippets.

@rmoch
Created January 7, 2014 08:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rmoch/8296176 to your computer and use it in GitHub Desktop.
Save rmoch/8296176 to your computer and use it in GitHub Desktop.
React
/** @jsx React.DOM */
// base on http://jsfiddle.net/spicyj/M6h22/
function copy(obj) {
var newObj = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
var ConditionFieldMixin = {
propTypes: {
data: React.PropTypes.string.isRequired,
// Will be called with the new value for the cell
onChange: React.PropTypes.func.isRequired
},
handleChange: function(evt) {
this.props.onChange(evt.target.value);
}
}
var ConditionField = React.createClass({
mixins: [ConditionFieldMixin],
render: function() {
return (
<select value={this.props.data} onChange={this.handleChange}>
<option value="">Selectionnez un champ</option>
<option value="FIELD1">Champ 1</option>
<option value="FIELD2">Champ 2</option>
</select>
);
}
});
var ConditionOperator = React.createClass({
mixins: [ConditionFieldMixin],
render: function() {
return (
<select value={this.props.data} onChange={this.handleChange}>
<option value="">Selectionnez un opérateur</option>
<option value="EQUAL">Egal à</option>
<option value="GT">Plus grand que</option>
</select>
);
}
});
var ConditionValue = React.createClass({
mixins: [ConditionFieldMixin],
render: function() {
return <input value={this.props.data} onChange={this.handleChange}/>;
}
});
var Condition = React.createClass({
propTypes: {
data: React.PropTypes.object.isRequired,
// Will be called with a cell's name and its new value
// onFieldChange: React.PropTypes.func.isRequired
},
handleChange: function(prop, val) {
// (Since this function simply calls this.props.onFieldChange, we could
// instead refer to the callback directly below.)
this.props.onFieldChange(prop, val);
},
render: function() {
return <span>
<ConditionField data={this.props.data.field}
onChange={this.handleChange.bind(null, "field")} />
<ConditionOperator data={this.props.data.operator}
onChange={this.handleChange.bind(null, "operator")} />
<ConditionValue data={this.props.data.value}
onChange={this.handleChange.bind(null, "value")} />
</span>;
}
});
var ConditionBlock = React.createClass({
propTypes: {
data: React.PropTypes.array.isRequired,
// Will be called with a cell's row index, name, and new value
},
deleteCondition: function(idx) {
this.props.data.splice(idx, 1);
this.forceUpdate();
},
addCondition: function() {
this.props.data.push({'id': this.props.data.length + 1, 'field': '', operator: '', value: ''})
this.forceUpdate();
},
render: function() {
var conditions = this.props.data.map(function(rowData, index) {
return <div>
<Condition key={index} data={rowData} />
<button type="button" onClick={this.deleteCondition.bind(null, index)}>Delete</button>
</div>
}, this);
return <div className="">{conditions}
<button type="button" onClick={this.addCondition}>Add Condition</button>
</div>;
}
});
var Rule = React.createClass({
deleteConditionBlock: function(idx) {
this.props.data.blocks.splice(idx, 1);
this.forceUpdate();
},
addConditionBlock: function() {
this.props.data.blocks.push([{'id': this.props.data.length + 1, 'field': '', operator: '', value: ''}])
this.forceUpdate();
},
render: function() {
var conditions = this.props.data.blocks.map(function(rowData, index) {
return <div>
<ConditionBlock key={index} data={rowData} />
<button type="button" onClick={this.deleteConditionBlock.bind(null, index)}>Delete condition block</button>
</div>
}, this);
return <div className="">{conditions}
<button type="button" onClick={this.addConditionBlock}>Add Condition block</button>
</div>;
}
});
var Selector = React.createClass({
getInitialState: function() {
return {data: this.props.initialData};
},
handleCellChange: function(rowIdx, prop, val) {
// If we were lazy here, we would simply write
// this.state.data[rowIdx][prop] = val;
// this.forceUpdate();
// but mutating in this way can be confusing and prevents performance
// optimizations later, so we instead treat the current data as
// immutable and copy it when modifying:
var row = copy(this.state.data[rowIdx]);
row[prop] = val;
var rows = this.state.data.slice();
rows[rowIdx] = row;
this.setState({data: rows});
},
flushButtonClick: function(evt) {
console.log(this.state.data);
},
render: function() {
var rules = this.state.data.rules.map(function(ruleData, index) {
return <span>
<Rule data={ruleData} onFieldChange={this.handleCellChange} />
</span>;
}, this);
return <span>{rules}
<button type="button" onClick={this.flushButtonClick}>Flush Data</button>
</span>;
}
});
var selector = {
"type": "text_message",
"value": ["this is the message", "this is the rich message"],
"name": "text message selector",
"rules": [{
"value": ["an other message", "an other rich message"],
"blocks": [
[
{
"field": "FIELD1",
"operator": "EQUAL",
"value": "10"
},
{
"field": "FIELD2",
"operator": "EQUAL",
"value": "42"
}
],[
{
"field": "FIELD1",
"operator": "EQUAL",
"value": "0"
}
]
]
},
{
"value": ["yet an other message", "yet an other rich message"],
"blocks": [
[
{
"field": "floor",
"operator": "==",
"value": "2"
}
]
]
}]
}
React.renderComponent(
<Selector initialData={selector} />, document.getElementById('target2')
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment