Skip to content

Commit

Permalink
feat(Dropdown): add searchQuery prop (#2109)
Browse files Browse the repository at this point in the history
  • Loading branch information
layershifter authored Sep 23, 2017
1 parent da8e686 commit e056cd6
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React, { Component } from 'react'
import { Dropdown } from 'semantic-ui-react'

import { stateOptions } from '../common'
// stateOptions = [ { key: 'AL', value: 'AL', text: 'Alabama' }, ... ]

export default class DropdownExampleSearchQuery extends Component {
state = { searchQuery: '' }

handleChange = (e, { value }) => this.setState({
value,
searchQuery: '',
})

handleSearchChange = (e, searchQuery) => this.setState({ searchQuery })

render() {
const { searchQuery, value } = this.state

return (
<Dropdown
fluid
multiple
onChange={this.handleChange}
onSearchChange={this.handleSearchChange}
options={stateOptions}
placeholder='State'
search
searchQuery={searchQuery}
selection
value={value}
/>
)
}
}
11 changes: 11 additions & 0 deletions docs/app/Examples/modules/Dropdown/Usage/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react'
import { Message } from 'semantic-ui-react'

import ComponentExample from 'docs/app/Components/ComponentDoc/ComponentExample'
import ExampleSection from 'docs/app/Components/ComponentDoc/ExampleSection'
Expand Down Expand Up @@ -83,6 +84,16 @@ const DropdownUsageExamples = () => (
description='A dropdown implements a search input shorthand.'
examplePath='modules/Dropdown/Usage/DropdownExampleSearchInput'
/>
<ComponentExample
title='Search Query'
description='A dropdown allows to pass you the search query.'
examplePath='modules/Dropdown/Usage/DropdownExampleSearchQuery'
>
<Message info>
This example also shows how to override default bevahiour of the search query which keeps
entered value after selection.
</Message>
</ComponentExample>
<ComponentExample
title='Upward'
description='A dropdown can open its menu upward.'
Expand Down
6 changes: 6 additions & 0 deletions src/modules/Dropdown/Dropdown.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export interface DropdownProps {
/** Initial value of open. */
defaultOpen?: boolean;

/** Initial value of searchQuery. */
defaultSearchQuery?: string;

/** Currently selected label in multi-select. */
defaultSelectedLabel?: number | string;

Expand Down Expand Up @@ -216,6 +219,9 @@ export interface DropdownProps {
/** A shorthand for a search input. */
searchInput?: any;

/** Current value of searchQuery. Creates a controlled component. */
searchQuery?: string;

/** Define whether the highlighted item should be selected on blur. */
selectOnBlur?: boolean;

Expand Down
14 changes: 9 additions & 5 deletions src/modules/Dropdown/Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ export default class Dropdown extends Component {
/** Initial value of open. */
defaultOpen: PropTypes.bool,

/** Initial value of searchQuery. */
defaultSearchQuery: PropTypes.string,

/** Currently selected label in multi-select. */
defaultSelectedLabel: customPropTypes.every([
customPropTypes.demand(['multiple']),
Expand Down Expand Up @@ -284,6 +287,9 @@ export default class Dropdown extends Component {
PropTypes.object,
]),

/** Current value of searchQuery. Creates a controlled component. */
searchQuery: PropTypes.string,

// TODO 'searchInMenu' or 'search='in menu' or ??? How to handle this markup and functionality?

/** Define whether the highlighted item should be selected on blur. */
Expand Down Expand Up @@ -352,6 +358,7 @@ export default class Dropdown extends Component {

static autoControlledProps = [
'open',
'searchQuery',
'selectedLabel',
'value',
]
Expand Down Expand Up @@ -756,10 +763,7 @@ export default class Dropdown extends Component {
const newQuery = value

_.invoke(this.props, 'onSearchChange', e, { ...this.props, searchQuery: newQuery })
this.setState({
selectedIndex: 0,
searchQuery: newQuery,
})
this.trySetState({ searchQuery: newQuery }, { selectedIndex: 0 })

// open search dropdown on search query
if (!open && newQuery.length >= minCharacters) {
Expand Down Expand Up @@ -883,7 +887,7 @@ export default class Dropdown extends Component {

clearSearchQuery = () => {
debug('clearSearchQuery()')
this.setState({ searchQuery: '' })
this.trySetState({ searchQuery: '' })
}

setValue = (value) => {
Expand Down
19 changes: 19 additions & 0 deletions test/specs/modules/Dropdown/Dropdown-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ describe('Dropdown', () => {
'left', 'right', 'top', 'top left', 'top right', 'bottom', 'bottom left', 'bottom right',
])

describe('defaultSearchQuery', () => {
it('changes default value of searchQuery', () => {
shallow(<Dropdown defaultSearchQuery='foo' />)
.should.have.state('searchQuery', 'foo')
})
})

it('closes on blur', () => {
wrapperMount(<Dropdown options={options} />)
.simulate('click')
Expand Down Expand Up @@ -491,6 +498,18 @@ describe('Dropdown', () => {
})
})

describe('searchQuery', () => {
it('defaults to empty string', () => {
shallow(<Dropdown />)
.should.have.state('searchQuery', '')
})

it('passes value to state', () => {
shallow(<Dropdown searchQuery='foo' />)
.should.have.state('searchQuery', 'foo')
})
})

describe('selected item', () => {
it('defaults to the first item', () => {
wrapperShallow(<Dropdown options={options} selection />)
Expand Down

0 comments on commit e056cd6

Please sign in to comment.