Skip to content

Commit a01bdf4

Browse files
committed
Merge pull request #32 from nkbt/Allow-any-element-to-be-used
Allow any element to be used
2 parents 33b2d3b + aace86c commit a01bdf4

File tree

4 files changed

+151
-12
lines changed

4 files changed

+151
-12
lines changed

README.md

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
[![Dependencies](https://img.shields.io/david/nkbt/react-debounce-input.svg?style=flat-square)](https://david-dm.org/nkbt/react-debounce-input)
99
[![Dev Dependencies](https://img.shields.io/david/dev/nkbt/react-debounce-input.svg?style=flat-square)](https://david-dm.org/nkbt/react-debounce-input#info=devDependencies)
1010

11-
React component that renders Input with debounced onChange
12-
Can be used as drop-in replacement for `<input type="text" />`
13-
11+
React component that renders an Input, Textarea or other element with debounced onChange.
12+
Can be used as drop-in replacement for `<input type="text" />` or `<textarea />`
1413

1514

1615
![React Debounce Input](src/example/react-debounce-input.gif)
@@ -82,6 +81,35 @@ ReactDOM.render(<App />, appRoot);
8281

8382
## Options
8483

84+
#### `element` : PropTypes.string or React.PropTypes.func (default: "input")
85+
86+
You can specify element="textarea". For Example:
87+
88+
```js
89+
<DebounceInput element="textarea" />
90+
```
91+
92+
Will result in
93+
94+
```js
95+
<textarea />
96+
```
97+
98+
Note: when rendering a `<textarea />` you may wish to set `forceNotifyByEnter = {false}` so the user can make new lines without forcing notification of the current value.
99+
100+
This package has only been tested with `<input />` and `<textarea />` but should work with any element which has `value` and `onChange` props.
101+
102+
You can also use a custom react component as the element. For Example:
103+
104+
```js
105+
<DebounceInput element={CustomReactComponent} />
106+
```
107+
108+
Will result in
109+
110+
```js
111+
<CustomReactComponent />
112+
```
85113

86114
#### `onChange`: PropTypes.func.isRequired
87115

@@ -117,6 +145,7 @@ Same as `forceNotifyByEnter`, but notification will be sent when focus leaves th
117145

118146
```js
119147
<DebounceInput
148+
type="number"
120149
onChange={event => this.setState({value: event.target.value})}
121150
placeholder="Name"
122151
className="user-name" />
@@ -125,7 +154,8 @@ Same as `forceNotifyByEnter`, but notification will be sent when focus leaves th
125154
Will result in
126155

127156
```js
128-
<input type="text"
157+
<input
158+
type="number"
129159
placeholder="Name"
130160
className="user-name" />
131161
```

src/Component.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {shouldComponentUpdate} from 'react/lib/ReactComponentWithPureRenderMixin
55

66
export const DebounceInput = React.createClass({
77
propTypes: {
8+
element: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.func]),
9+
type: React.PropTypes.string,
810
onChange: React.PropTypes.func.isRequired,
911
onKeyDown: React.PropTypes.func,
1012
onBlur: React.PropTypes.func,
@@ -21,6 +23,8 @@ export const DebounceInput = React.createClass({
2123

2224
getDefaultProps() {
2325
return {
26+
element: 'input',
27+
type: 'text',
2428
minLength: 0,
2529
debounceTimeout: 100,
2630
forceNotifyByEnter: true,
@@ -111,6 +115,7 @@ export const DebounceInput = React.createClass({
111115

112116
render() {
113117
const {
118+
element,
114119
onChange: _onChange,
115120
value: _value,
116121
minLength: _minLength,
@@ -142,13 +147,13 @@ export const DebounceInput = React.createClass({
142147
}
143148
} : {};
144149

145-
return (
146-
<input type="text"
147-
{...props}
148-
onChange={this.onChange}
149-
value={this.state.value}
150-
{...onKeyDown}
151-
{...onBlur} />
152-
);
150+
151+
return React.createElement(element, {
152+
...props,
153+
onChange: this.onChange,
154+
value: this.state.value,
155+
...onKeyDown,
156+
...onBlur
157+
});
153158
}
154159
});

src/example/App/Textarea.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import React from 'react';
2+
import DebounceInput from '../..';
3+
import css from './App.css';
4+
5+
6+
const Textarea = React.createClass({
7+
getInitialState() {
8+
return {
9+
value: '',
10+
minLength: 0,
11+
debounceTimeout: 500,
12+
infinite: false,
13+
forceNotifyByEnter: false,
14+
forceNotifyOnBlur: true
15+
};
16+
},
17+
18+
19+
render() {
20+
const {
21+
minLength, infinite, debounceTimeout,
22+
forceNotifyByEnter, forceNotifyOnBlur,
23+
value, key
24+
} = this.state;
25+
26+
return (
27+
<div>
28+
<div className={css.config}>
29+
<label className={css.label}>
30+
Min length:
31+
<input className={css.input}
32+
type="range"
33+
value={minLength} step={1} min={0} max={10}
34+
onChange={e => this.setState({minLength: parseInt(e.target.value, 10)})} />
35+
{minLength}
36+
</label>
37+
38+
<label className={css.label}>
39+
Debounce timeout:
40+
<input className={css.input}
41+
type="range"
42+
disabled={infinite}
43+
value={debounceTimeout} step={100} min={0} max={2000}
44+
onChange={e => this.setState({debounceTimeout: parseInt(e.target.value, 10)})} />
45+
{debounceTimeout}
46+
</label>
47+
48+
<label className={css.label}>
49+
Infinite timeout:
50+
<input className={css.input}
51+
type="checkbox"
52+
checked={infinite}
53+
onChange={e => this.setState({infinite: e.target.checked})} />
54+
</label>
55+
</div>
56+
57+
<div className={css.config}>
58+
<label className={css.label}>
59+
Notify by:
60+
</label>
61+
62+
<label className={css.label}>
63+
"Enter" keypress:
64+
<input className={css.input}
65+
type="checkbox"
66+
checked={forceNotifyByEnter}
67+
onChange={e => this.setState({forceNotifyByEnter: e.target.checked})} />
68+
</label>
69+
70+
<label className={css.label}>
71+
Blur:
72+
<input className={css.input}
73+
type="checkbox"
74+
checked={forceNotifyOnBlur}
75+
onChange={e => this.setState({forceNotifyOnBlur: e.target.checked})} />
76+
</label>
77+
</div>
78+
79+
<DebounceInput
80+
cols="60"
81+
rows="7"
82+
element="textarea"
83+
forceNotifyByEnter={forceNotifyByEnter}
84+
forceNotifyOnBlur={forceNotifyOnBlur}
85+
minLength={minLength}
86+
debounceTimeout={infinite ? -1 : debounceTimeout}
87+
onChange={e => this.setState({value: e.target.value})}
88+
onKeyDown={e => this.setState({key: e.key})} />
89+
<p>Value: {value}</p>
90+
<p>Key pressed: {key}</p>
91+
</div>
92+
93+
);
94+
}
95+
});
96+
97+
98+
export default Textarea;

src/example/App/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import Controllable from './Controllable';
33
import Customizable from './Customizable';
44
import UndoRedo from './UndoRedo';
5+
import Textarea from './Textarea';
56
import css from './App.css';
67

78

@@ -22,6 +23,11 @@ const App = () => (
2223
<h2>Example 3. Undo-Redo</h2>
2324
<UndoRedo />
2425
</section>
26+
27+
<section className={css.section}>
28+
<h2>Example 4. Debounced Textarea</h2>
29+
<Textarea />
30+
</section>
2531
</div>
2632
);
2733

0 commit comments

Comments
 (0)