react-native-modal-selector-searchable
Version:
A cross-platform (iOS / Android), selector/picker component for React Native that is filterable, highly customizable and supports sections.
201 lines (166 loc) • 15.2 kB
Markdown
# react-native-modal-selector-searchable [](https://badge.fury.io/js/react-native-modal-selector-searchable)
A cross-platform (iOS / Android), selector/picker component for React Native that is highly customizable and supports sections.
##### Search functionality has been added to this fork repository
This project was forked from [react-native-modal-selector](https://github.com/peacechen/react-native-modal-selector)
## Change log
### v2.1.6
- Added `placeholderTextColor` and `keyboardType` props on search field ([faslash](https://github.com/faslash))
### v2.1.5
- Added `searchAutoFocus` prop for `autofocus` on search field ([jonacds](https://github.com/jonacds))
## Demo
<img src="docs/demo.gif" />
## Install
```sh
npm i react-native-modal-selector-searchable --save
```
## Usage
You can either use this component in its default mode, as a wrapper around your existing component or provide a custom component (where you need to control opening of the modal yourself). In default mode a customizable button is rendered.
See `SampleApp` for an example how to use this component.
```jsx
import ModalSelector from 'react-native-modal-selector-searchable'
class SampleApp extends Component {
constructor(props) {
super(props);
this.state = {
textInputValue: ''
}
}
render() {
let index = 0;
const data = [
{ key: index++, section: true, label: 'Fruits' },
{ key: index++, label: 'Red Apples' },
{ key: index++, label: 'Cherries' },
{ key: index++, label: 'Cranberries', accessibilityLabel: 'Tap here for cranberries' },
// etc...
// Can also add additional custom keys which are passed to the onChange callback
{ key: index++, label: 'Vegetable', customKey: 'Not a fruit' }
];
return (
<View style={{flex:1, justifyContent:'space-around', padding:50}}>
// Default mode
<ModalSelector
data={data}
initValue="Select something yummy!"
onChange={(option)=>{ alert(`${option.label} (${option.key}) nom nom nom`) }} />
// Wrapper
<ModalSelector
data={data}
initValue="Select something yummy!"
supportedOrientations={['landscape']}
accessible={true}
scrollViewAccessibilityLabel={'Scrollable options'}
cancelButtonAccessibilityLabel={'Cancel Button'}
onChange={(option)=>{ this.setState({textInputValue:option.label})}}>
<TextInput
style={{borderWidth:1, borderColor:'#ccc', padding:10, height:30}}
editable={false}
placeholder="Select something yummy!"
value={this.state.textInputValue} />
</ModalSelector>
// Custom component
<ModalSelector
data={data}
ref={selector => { this.selector = selector; }}
customSelector={<Switch onValueChange={() => this.selector.open()} />}
/>
</View>
);
}
}
```
## Data Format
The selector accepts a specific format of data:
```javascript
[{ key: 5, label: 'Red Apples' }]
```
Optionally provide a `component` key which overrides the default label text. Optionally provide a unique `testID` for each item:
```javascript
[{
key: 5,
label: 'Red Apples',
// The next keys are optional --
component: <View style={{backgroundColor: 'red'}}><Text style={{color: 'white'}}>Red Apples custom component ☺</Text></View>,
testID: '5-red-apples'
}]
```
<img src="docs/image-1.png" />
If your data has a specific format, you can define extractors of data, example:
```javascript
this.setState({data: [{ id: 5, name: 'Red Apples' }]});
return (
<ModalSelector
data={this.state.data}
keyExtractor= {item => item.id}
labelExtractor= {item => item.name}
/>
);
```
## API
### Props
Prop | Type | Optional | Default | Description
------------------------------- | ------------------------ | -------- | ------------------------------ | -----------
`data` | array | No | [] | array of objects with a unique `key` and `label` to select in the modal. Optional `component` overrides label text. Optional unique `testID` for each item.
`search` | bool | Yes | true | Control the search box visibility
`hideSectionOnSearch` | bool | Yes | false | Hide the caption of related matched items
`caseSensitiveSearch` | bool | Yes | false | Sensitive mode on search
`frozenSearch` | bool | Yes | false | Preserve initial modal size on search
`fullHeight` | bool | Yes | false | Keep the modal size to the maximum regardless of the listed items
`onSearchFilterer` | function | Yes |(searchText, data) => filteredData | Custom search filterer function.
`onChange` | function | Yes | () => {} | callback function, when the users has selected an option
`onChangeSearch` | function | Yes | (searchData) => {} | Callback function, when the users has typed in search box
`onModalOpen` | function | Yes | () => {} | callback function, when modal is opening
`onModalClose` | function | Yes | (item) => {} | callback function, when modal is closing. Returns the selected item.
`onCancel` | function | Yes | () => {} | callback function, when clicking the cancel button
`keyExtractor` | function | Yes | (data) => data.key | extract the key from the data item
`labelExtractor` | function | Yes | (data) => data.label | extract the label from the data item
`componentExtractor` | function | Yes | (data) => data.component | extract the component from the data item
`visible` | bool | Yes | false | control open/close state of modal
`closeOnChange` | bool | Yes | true | control if modal closes on select
`initValue` | string | Yes | `Select me!` | text that is initially shown on the button
`cancelText` | string | Yes | `cancel` | text of the cancel button
`searchText` | string | Yes | `search` | text of the search placeholder
`disabled` | bool | Yes | false | `true` disables opening of the modal
`supportedOrientations` | ['portrait', 'landscape'] | Yes | both | orientations the modal supports
`keyboardShouldPersistTaps` | `string` / `bool` | Yes | `always` | passed to underlying ScrollView
`listType` | string | Yes | `SCROLLVIEW` | scroller type: `SCROLLVIEW` or `FLATLIST`
`animationType` | string | Yes | `slide` | type of animation to be used to show the modal. Must be one of `none`, `slide` or `fade`.
`style` | object | Yes | | style definitions for the root element
`childrenContainerStyle` | object | Yes | {} | style definitions for the children container view
`touchableStyle` | object | Yes | {} | style definitions for the touchable element
`touchableActiveOpacity` | number | Yes | 0.2 | opacity for the touchable element on touch
`selectStyle` | object | Yes | {} | style definitions for the select element (available in default mode only!). NOTE: Due to breaking changes in React Native, RN < 0.39.0 should pass `flex:1` explicitly to `selectStyle` as a prop.
`selectTextStyle` | object | Yes | {} | style definitions for the select element (available in default mode only!)
`overlayStyle` | object | Yes | { flex: 1, padding: '5%', justifyContent: 'center', backgroundColor: 'rgba(0,0,0,0.7)' } | style definitions for the overlay background element. RN <= 0.41 should override this with pixel value for padding.
`sectionStyle` | object | Yes | {} | style definitions for the section element
`sectionTextStyle` | object | Yes | {} | style definitions for the select text element
`selectedItemTextStyle` | object | Yes | {} | style definitions for the currently selected text element
`optionStyle` | object | Yes | {} | style definitions for the option element
`optionTextStyle` | object | Yes | {} | style definitions for the option text element
`optionContainerStyle` | object | Yes | {} | style definitions for the option container element
`cancelStyle` | object | Yes | {} | style definitions for the cancel element
`cancelTextStyle` | object | Yes | {} | style definitions for the cancel text element
`initValueTextStyle` | object | Yes | {} | style definitions for the initValue text element
`cancelContainerStyle` | object | Yes | {} | style definitions for the cancel container
`searchStyle` | object | Yes | {} | Style definitions for the search view element
`searchTextStyle` | object | Yes | {} | Style definitions for the search text element
`backdropPressToClose` | bool | Yes | false | `true` makes the modal close when the overlay is pressed
`passThruProps` | object | Yes | {} | props to pass through to the container View and each option TouchableOpacity (e.g. testID for testing)
`selectTextPassThruProps` | object | Yes | {} | props to pass through to the select text component
`optionTextPassThruProps` | object | Yes | {} | props to pass through to the options text components in the modal
`cancelTextPassThruProps` | object | Yes | {} | props to pass through to the cancel text components in the modal
`scrollViewPassThruProps` | object | Yes | {} | props to pass through to the internal ScrollView
`openButtonContainerAccessible` | bool | Yes | false | `true` enables accessibility for the open button container. Note: if `false` be sure to define accessibility props directly in the wrapped component.
`listItemAccessible` | bool | Yes | false | `true` enables accessibility for data items. Note: data items should have an `accessibilityLabel` property if this is enabled
`cancelButtonAccessible` | bool | Yes | false | `true` enables accessibility for cancel button.
`scrollViewAccessible` | bool | Yes | false | `true` enables accessibility for the scroll view. Only enable this if you don't want to interact with individual data items.
`scrollViewAccessibilityLabel` | string | Yes | undefined | Accessibility label for the modal ScrollView
`cancelButtonAccessibilityLabel`| string | Yes | undefined | Accessibility label for the cancel button
`modalOpenerHitSlop` | object | Yes | {} | How far touch can stray away from touchable that opens modal ([RN docs](https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html#hitslop))
`customSelector` | node | Yes | undefined | Render a custom node instead of the built-in select box.
`selectedKey` | any | Yes | '' | Key of the item to be initially selected
`enableShortPress` | bool | Yes | true | enables short press. This is regular touch behavior.
`enableLongPress` | bool | Yes | false | enables long press. When true, `onModalOpen` returns `{longPress: true}`
`optionsTestIDPrefix` | string | Yes | `'default'` | This prefixes each selectable option's testID prop if no testID keys are provided in `props.data` array objects. Default for each option's testID: 'default-\<optionLabel\>'
### Methods
`getSelectedItem()`: get current selected item, updated by onChange event.