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

[added] Allow users to opt-out of the wrapper element #364

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -190,6 +190,13 @@ Default value: `''`

The value to display in the input field

#### `wrapper: Boolean` (optional)
Default value: `true`

Whether or not to wrap the input and menu items in a `<div>` tag. Setting
this to `false` will render without a wrapper, discarding any overrides from
`wrapperProps` and `wrapperStyle`.

#### `wrapperProps: Object` (optional)
Default value: `{}`

72 changes: 45 additions & 27 deletions lib/Autocomplete.js
Original file line number Diff line number Diff line change
@@ -121,6 +121,10 @@ class Autocomplete extends React.Component {
* placeholder, event handlers (onFocus, onBlur, etc.), autoFocus, etc..
*/
inputProps: PropTypes.object,
/**
* Whether or not to wrap the input and menu items in a div.
*/
wrapper: PropTypes.bool,
/**
* Props that are applied to the element which wraps the `<input />` and
* dropdown menu elements rendered by `Autocomplete`.
@@ -161,19 +165,20 @@ class Autocomplete extends React.Component {

static defaultProps = {
value: '',
wrapper: true,
wrapperProps: {},
wrapperStyle: {
display: 'inline-block'
},
inputProps: {},
renderInput(props) {
return <input {...props} />
return <input key="autocomplete:input" {...props} />
},
onChange() {},
onSelect() {},
isItemSelectable() { return true },
renderMenu(items, value, style) {
return <div style={{ ...style, ...this.menuStyle }} children={items}/>
return <div key="autocomplete:menu" style={{ ...style, ...this.menuStyle }} children={items}/>
},
menuStyle: {
borderRadius: '3px',
@@ -475,6 +480,7 @@ class Autocomplete extends React.Component {
}
const menu = this.props.renderMenu(items, this.props.value, style)
return React.cloneElement(menu, {
key: 'autocomplete:menu',
ref: e => this.refs.menu = e,
// Ignore blur to prevent menu from de-rendering before we can process click
onTouchStart: () => this.setIgnoreBlur(true),
@@ -570,32 +576,44 @@ class Autocomplete extends React.Component {

const { inputProps } = this.props
const open = this.isOpen()
return (
<div style={{ ...this.props.wrapperStyle }} {...this.props.wrapperProps}>
{this.props.renderInput({
...inputProps,
role: 'combobox',
'aria-autocomplete': 'list',
'aria-expanded': open,
autoComplete: 'off',
ref: this.exposeAPI,
onFocus: this.handleInputFocus,
onBlur: this.handleInputBlur,
onChange: this.handleChange,
onKeyDown: this.composeEventHandlers(this.handleKeyDown, inputProps.onKeyDown),
onClick: this.composeEventHandlers(this.handleInputClick, inputProps.onClick),
value: this.props.value,
})}
{open && this.renderMenu()}
{this.props.debug && (
<pre style={{ marginLeft: 300 }}>
{JSON.stringify(this._debugStates.slice(Math.max(0, this._debugStates.length - 5), this._debugStates.length), null, 2)}
</pre>
)}
</div>
)
const input = this.props.renderInput({
...inputProps,
role: 'combobox',
'aria-autocomplete': 'list',
'aria-expanded': open,
autoComplete: 'off',
ref: this.exposeAPI,
onFocus: this.handleInputFocus,
onBlur: this.handleInputBlur,
onChange: this.handleChange,
onKeyDown: this.composeEventHandlers(this.handleKeyDown, inputProps.onKeyDown),
onClick: this.composeEventHandlers(this.handleInputClick, inputProps.onClick),
value: this.props.value,
})

const menu = open ? this.renderMenu() : null

const debug = this.props.debug ? (
<pre key="autocomplete:debug" style={{ marginLeft: 300 }}>
{JSON.stringify(this._debugStates.slice(Math.max(0, this._debugStates.length - 5), this._debugStates.length), null, 2)}
</pre>
) : null

if (this.props.wrapper) {
return (
<div
style={{ ...this.props.wrapperStyle }}
{...this.props.wrapperProps}
>
{input}
{menu}
{debug}
</div>
)
} else {
return [input, menu, debug]
}
}
}

module.exports = Autocomplete