+102
-0
lines changedFilter options
+102
-0
lines changed Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
1
+
import React, {Component, PropTypes} from "react";
2
+
3
+
import {noop, debounce, defaults, values} from "lodash";
4
+
5
+
import {getValueFromEvent} from "common/utils/clientUtils";
6
+
7
+
class FormEditWrapper extends Component {
8
+
static propTypes = {
9
+
value : PropTypes.object.isRequired,
10
+
isEditing : PropTypes.bool,
11
+
onChange : PropTypes.func,
12
+
valuePropName : PropTypes.string,
13
+
onChangePropName : PropTypes.string,
14
+
singleValue : PropTypes.bool,
15
+
passIsEditing : PropTypes.bool,
16
+
dispatchDelay : PropTypes.number,
17
+
}
18
+
19
+
static defaultProps = {
20
+
isEditing : true,
21
+
onChange : noop,
22
+
valuePropName : "value",
23
+
onChangePropName : "onChange",
24
+
singleValue : false,
25
+
passIsEditing : true,
26
+
dispatchDelay : 250,
27
+
}
28
+
29
+
constructor(props) {
30
+
super(props);
31
+
const boundDispatchAttributes = this.dispatchAttributeChange.bind(this);
32
+
this.dispatchAttributeChange = debounce(boundDispatchAttributes, props.dispatchDelay);
33
+
34
+
this.state = {
35
+
value : {},
36
+
};
37
+
}
38
+
39
+
componentWillReceiveProps() {
40
+
// Reset any component-local changes Note that the incoming props
41
+
// SHOULD match the changes we just had in local state.
42
+
this.setState({value : {}});
43
+
}
44
+
45
+
onChildChange = (e) => {
46
+
const {isEditing} = this.props;
47
+
48
+
if(isEditing) {
49
+
const newValues = getValueFromEvent(e);
50
+
51
+
if(newValues) {
52
+
const change = {
53
+
...this.state.value,
54
+
...newValues
55
+
};
56
+
57
+
// Update our component-local state with these changes, so that the child components
58
+
// will re-render with the new values right away
59
+
this.setState({value : change});
60
+
61
+
// Because this is debounced, we will only call the passed-in props.onChange
62
+
// once there is a pause in changes (like letting go of a held-down key)
63
+
this.dispatchAttributeChange(change);
64
+
}
65
+
}
66
+
}
67
+
68
+
dispatchAttributeChange(change) {
69
+
this.props.onChange(change);
70
+
}
71
+
72
+
render() {
73
+
const {value : propsValue, children} = this.props;
74
+
const {isEditing, passIsEditing, valuePropName, onChangePropName, singleValue} = this.props;
75
+
const {value : stateValue = {}} = this.state;
76
+
77
+
// Use incoming values from props IF there is no corresponding value
78
+
// in local component state. This allows local changes to win out.
79
+
const currentValues = defaults({}, stateValue, propsValue);
80
+
81
+
let valueToPassDown = currentValues;
82
+
83
+
if(singleValue) {
84
+
valueToPassDown = values(currentValues)[0];
85
+
}
86
+
87
+
const editingValue = passIsEditing ? {isEditing} : {};
88
+
89
+
// Force the child form to re-render itself with these values
90
+
const child = React.Children.only(children);
91
+
92
+
const updatedChild = React.cloneElement(child, {
93
+
[valuePropName] : valueToPassDown,
94
+
[onChangePropName] : this.onChildChange,
95
+
...editingValue
96
+
});
97
+
98
+
return updatedChild;
99
+
}
100
+
}
101
+
102
+
export default FormEditWrapper;
You can’t perform that action at this time.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4