Skip to content
This repository was archived by the owner on Jul 19, 2019. It is now read-only.

Commit 1e42ec1

Browse files
author
Johannes Reuter
committed
Add renderWrapper prop
1 parent 41388f7 commit 1e42ec1

File tree

5 files changed

+98
-20
lines changed

5 files changed

+98
-20
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ We try to follow [http://keepachangelog.com/](http://keepachangelog.com/) recomm
33

44
## [Unreleased]
55
_(add items here for easier creation of next log entry)_
6+
### Added
7+
- `props.renderWrapper` which allows a custom rendering function for the wrapper element of input and menu
68

79
## [1.8.1] - 2018-02-11
810
### Fixed

examples/custom-menu/app.js

+7
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ class App extends React.Component {
6060
) : items}
6161
</div>
6262
)}
63+
renderWrapper={(wrapperStyles, wrapperProps, renderedInput, renderedMenu, renderedDebugInfo) => (
64+
<span style = {{ ...wrapperStyles }} {...wrapperProps}>
65+
Enter value here: {renderedInput}
66+
{renderedMenu}
67+
{renderedDebugInfo}
68+
</span>
69+
)}
6370
isItemSelectable={(item) => !item.header}
6471
/>
6572
</div>

lib/Autocomplete.js

+42-20
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,21 @@ class Autocomplete extends React.Component {
132132
* will win if it contains a `style` entry.
133133
*/
134134
wrapperStyle: PropTypes.object,
135+
/**
136+
* Arguments: `wrapperStyles: Object, wrapperProps: Object,
137+
* renderedInput: Any, renderedMenu: Any`
138+
*
139+
* Invoked to generate the wrapper element. The `wrapperStyles` and
140+
* `wrapperProps` objects are the corresponding properties of the
141+
* `<Autocomplete />` component itself.
142+
* `renderedInput` and `renderedMenu` are the generated input and
143+
* menu elements.
144+
* The default implementation uses a div-element as the wrapper with input
145+
* and menu as direct children. You can use this function to change the
146+
* wrapper, e.g. by using an inline-element like span or omit it completely
147+
* by using a fragment (supported from react version 16).
148+
*/
149+
renderWrapper: PropTypes.func,
135150
/**
136151
* Whether or not to automatically highlight the top match in the dropdown
137152
* menu.
@@ -175,6 +190,13 @@ class Autocomplete extends React.Component {
175190
renderMenu(items, value, style) {
176191
return <div style={{ ...style, ...this.menuStyle }} children={items}/>
177192
},
193+
renderWrapper(wrapperStyle, wrapperProps, renderedInput, renderedMenu, renderedDebugInfo) {
194+
return (<div style={{ ...wrapperStyle }} {...wrapperProps}>
195+
{renderedInput}
196+
{renderedMenu}
197+
{renderedDebugInfo}
198+
</div>)
199+
},
178200
menuStyle: {
179201
borderRadius: '3px',
180202
boxShadow: '0 2px 12px rgba(0, 0, 0, 0.1)',
@@ -570,29 +592,29 @@ class Autocomplete extends React.Component {
570592

571593
const { inputProps } = this.props
572594
const open = this.isOpen()
573-
return (
574-
<div style={{ ...this.props.wrapperStyle }} {...this.props.wrapperProps}>
575-
{this.props.renderInput({
576-
...inputProps,
577-
role: 'combobox',
578-
'aria-autocomplete': 'list',
579-
'aria-expanded': open,
580-
autoComplete: 'off',
581-
ref: this.exposeAPI,
582-
onFocus: this.handleInputFocus,
583-
onBlur: this.handleInputBlur,
584-
onChange: this.handleChange,
585-
onKeyDown: this.composeEventHandlers(this.handleKeyDown, inputProps.onKeyDown),
586-
onClick: this.composeEventHandlers(this.handleInputClick, inputProps.onClick),
587-
value: this.props.value,
588-
})}
589-
{open && this.renderMenu()}
590-
{this.props.debug && (
595+
return this.props.renderWrapper(
596+
this.props.wrapperStyle,
597+
this.props.wrapperProps,
598+
this.props.renderInput({
599+
...inputProps,
600+
role: 'combobox',
601+
'aria-autocomplete': 'list',
602+
'aria-expanded': open,
603+
autoComplete: 'off',
604+
ref: this.exposeAPI,
605+
onFocus: this.handleInputFocus,
606+
onBlur: this.handleInputBlur,
607+
onChange: this.handleChange,
608+
onKeyDown: this.composeEventHandlers(this.handleKeyDown, inputProps.onKeyDown),
609+
onClick: this.composeEventHandlers(this.handleInputClick, inputProps.onClick),
610+
value: this.props.value,
611+
}),
612+
open && this.renderMenu(),
613+
this.props.debug && (
591614
<pre style={{ marginLeft: 300 }}>
592615
{JSON.stringify(this._debugStates.slice(Math.max(0, this._debugStates.length - 5), this._debugStates.length), null, 2)}
593616
</pre>
594-
)}
595-
</div>
617+
)
596618
)
597619
}
598620
}

lib/__tests__/Autocomplete-test.js

+22
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,28 @@ describe('Autocomplete mouse event handlers', () => {
651651
})
652652
})
653653

654+
describe('Autocomplete.props.renderWrapper', () => {
655+
it('should be invoked in `render` to render the root element', () => {
656+
const renderWrapper = jest.fn((wrapperStyles, wrapperProps, renderedInput, renderedMenu, renderedDebugInfo) => {
657+
expect(wrapperStyles).toMatchSnapshot()
658+
expect(wrapperProps).toMatchSnapshot()
659+
return (
660+
<span>
661+
{renderedInput}
662+
{renderedMenu}
663+
{renderedDebugInfo}
664+
</span>
665+
)
666+
})
667+
const tree = shallow(AutocompleteComponentJSX({
668+
value: 'pants',
669+
renderWrapper,
670+
}))
671+
expect(renderWrapper).toHaveBeenCalledTimes(1)
672+
expect(tree).toMatchSnapshot()
673+
})
674+
})
675+
654676
describe('Autocomplete.props.renderInput', () => {
655677
it('should be invoked in `render` to create the <input> element', () => {
656678
const renderInput = jest.fn(props => {

lib/__tests__/__snapshots__/Autocomplete-test.js.snap

+25
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,28 @@ exports[`Autocomplete.props.renderInput should be invoked in \`render\` to creat
4242
</div>
4343
</div>
4444
`;
45+
46+
exports[`Autocomplete.props.renderWrapper should be invoked in \`render\` to render the root element 1`] = `
47+
Object {
48+
"display": "inline-block",
49+
}
50+
`;
51+
52+
exports[`Autocomplete.props.renderWrapper should be invoked in \`render\` to render the root element 2`] = `Object {}`;
53+
54+
exports[`Autocomplete.props.renderWrapper should be invoked in \`render\` to render the root element 3`] = `
55+
<span>
56+
<input
57+
aria-autocomplete="list"
58+
aria-expanded={false}
59+
autoComplete="off"
60+
onBlur={[Function]}
61+
onChange={[Function]}
62+
onClick={[Function]}
63+
onFocus={[Function]}
64+
onKeyDown={[Function]}
65+
role="combobox"
66+
value="pants"
67+
/>
68+
</span>
69+
`;

0 commit comments

Comments
 (0)