UNPKG

dropdown-picker-rn

Version:

A single / multiple, categorizable & searchable item picker (dropdown) component for react native which supports both Android & iOS.

696 lines (531 loc) 27.2 kB
# React native dropdown picker v4 ### NOTE: THIS IS FORKED VERSION OF https://github.com/hossein-zare/react-native-dropdown-picker ### The only changes applied are mentioned in this comment: https://github.com/hossein-zare/react-native-dropdown-picker/issues/84#issuecomment-742657954 A single / multiple, categorizable & searchable item picker (dropdown) component for react native which supports both Android & iOS. ## Screenshots ![Screenshot](https://raw.githubusercontent.com/hossein-zare/react-native-dropdown-picker/4.x/screenshots/1.png) ![Screenshot](https://raw.githubusercontent.com/hossein-zare/react-native-dropdown-picker/4.x/screenshots/2.png) ## Table of contents - [React native dropdown picker v4](#react-native-dropdown-picker-v4) - [NOTE: THIS IS SAME LIBRARY WITH https://github.com/hossein-zare/react-native-dropdown-picker](#note-this-is-same-library-with-httpsgithubcomhossein-zarereact-native-dropdown-picker) - [The only changes applied are mentioned in this comment: https://github.com/hossein-zare/react-native-dropdown-picker/issues/84#issuecomment-742657954](#the-only-changes-applied-are-mentioned-in-this-comment-httpsgithubcomhossein-zarereact-native-dropdown-pickerissues84issuecomment-742657954) - [Screenshots](#screenshots) - [Table of contents](#table-of-contents) - [Dependencies](#dependencies) - [Changelog](#changelog) - [Getting Started](#getting-started) - [Installation](#installation) - [via NPM](#via-npm) - [via Yarn](#via-yarn) - [Basic Usage](#basic-usage) - [Single Item](#single-item) - [Multiple Items](#multiple-items) - [Available Item Properties](#available-item-properties) - [Category Support](#category-support) - [Searchable Items](#searchable-items) - [Default Item](#default-item) - [Placeholder](#placeholder) - [Controller](#controller) - [Class Components](#class-components) - [Functional Components](#functional-components) - [Styling The Component](#styling-the-component) - [RTL Support](#rtl-support) - [FAQ](#faq) - [How to close other pickers when opening another picker?](#how-to-close-other-pickers-when-opening-another-picker) - [borderRadius](#borderradius) - [zIndex conflicts (Untouchable Items, Overlapping pickers)](#zindex-conflicts-untouchable-items-overlapping-pickers) - [Dropdown Overflow](#dropdown-overflow) - [Props](#props) ## Dependencies Make sure `react-native-vector-icons` is installed. https://github.com/oblador/react-native-vector-icons ## Changelog - Added `childrenContainerStyle`. [Februrary 13, 2021] - Added `textStyle` `viewStyle` & `untouchable` props to items. [Februrary 13, 2021] - Added category support. [Februrary 13, 2021] - Added `globalTextStyle`. [February 11, 2021] - Added `onSearch`. [January 27, 2021] - Added `labelProps`. [January 06, 2021] - Some bug-fixes. [January 06, 2021] - Added `containerProps`. [December 21, 2020] ## Getting Started ### Installation ##### via NPM ```sh npm install react-native-dropdown-picker --save ``` ##### via Yarn ```sh yarn add react-native-dropdown-picker ``` ### Basic Usage The first step is to import the package. ```javascript import DropDownPicker from 'react-native-dropdown-picker'; ``` #### Single Item Select a single item. ```javascript import Icon from 'react-native-vector-icons/Feather'; this.state = { country: 'uk' } <DropDownPicker items={[ {label: 'USA', value: 'usa', icon: () => <Icon name="flag" size={18} color="#900" />, hidden: true}, {label: 'UK', value: 'uk', icon: () => <Icon name="flag" size={18} color="#900" />}, {label: 'France', value: 'france', icon: () => <Icon name="flag" size={18} color="#900" />}, ]} defaultValue={this.state.country} containerStyle={{height: 40}} style={{backgroundColor: '#fafafa'}} itemStyle={{ justifyContent: 'flex-start' }} dropDownStyle={{backgroundColor: '#fafafa'}} onChangeItem={item => this.setState({ country: item.value })} /> ``` #### Multiple Items Select multiple items. ```javascript import Icon from 'react-native-vector-icons/Feather'; this.state = { countries: ['uk'] } <DropDownPicker items={[ {label: 'UK', value: 'uk', icon: () => <Icon name="flag" size={18} color="#900" />}, {label: 'France', value: 'france', icon: () => <Icon name="flag" size={18} color="#900" />}, ]} multiple={true} multipleText="%d items have been selected." min={0} max={10} defaultValue={this.state.countries} containerStyle={{height: 40}} itemStyle={{ justifyContent: 'flex-start' }} onChangeItem={item => this.setState({ countries: item // an array of the selected items })} /> ``` ### Available Item Properties Here's the type definition of an item. ```ts type ItemType = { label: any; // required value: any; // required icon?: () => JSX.Element; hidden?: boolean; untouchable?: boolean; parent?: any; disabled?: boolean; selected?: boolean; viewStyle?: StyleProp<ViewStyle>, textStyle?: StyleProp<TextStyle>, }; ``` ### Category Support As of v4.x, You can simply categorize your items. ```jsx <DropDownPicker items={[ {label: 'North America', value: 'na', untouchable: true}, // North America {label: 'United States', value: 'us', parent: 'na'}, {label: 'Canada', value: 'canada', parent: 'na'}, {label: 'Mexico', value: 'mexico', parent: 'na'}, {label: 'Europe', value: 'eu', untouchable: true}, // Europe {label: 'UK', value: 'uk', parent: 'eu'}, {label: 'Germany', value: 'germany', parent: 'eu'}, {label: 'Russia', value: 'russia', parent: 'eu'}, ]} ... /> ``` > The `parent` property must be equal to the `value` property of the parent item. > The `untouchable` property makes the item untouchable. ### Searchable Items Search for specific items. ```javascript searchable={true} searchablePlaceholder="Search for an item" searchablePlaceholderTextColor="gray" seachableStyle={{}} searchableError={() => <Text>Not Found</Text>} onSearch={text => { // Example if (this._API.isFetching()) this._API.abort(); this._API = this.fetchFromServer(text, (items) => { // See controller: https://github.com/hossein-zare/react-native-dropdown-picker#controller this.controller.resetItems(items); // Maybe a new method will be introduced for a better UX! }); }} ``` ### Default Item You may want to select one of the items as default. **Use one of the following options:** 1. Add `selected: true` to the object. **(This method is not state-friendly!)** ```javascript items={[ {label: 'Item 1', value: 'item1'}, {label: 'Item 2', value: 'item2', selected: true}, ]} ``` 2. The `defaultValue` property. ```javascript defaultValue = 'uk'; // Single defaultValue = ['uk']; // Multiple ``` ### Placeholder You may want to have a placeholder while the default value is null or an empty array. Add the following properties to the component. ```javascript this.state = { data: null, // Single data: [] // Multiple } ... defaultValue={this.state.data} placeholder="Select an item" ... ``` ### Controller The `controller` property gives you full access to the DropDownPicker methods and properties. ##### Class Components ```javascript constructor(props) { this.state = { value: null, items: [] } this.controller; } <DropDownPicker items={this.state.items} controller={instance => this.controller = instance} onChangeList={(items, callback) => { this.setState({ items // items: items }, callback); }} defaultValue={this.state.value} onChangeItem={item => this.setState({ value: item.value })} /> ``` ##### Functional Components ```javascript const [value, setValue] = useState(null); const [items, setItems] = useState([ {...}, ... ]); let controller; <DropDownPicker items={items} controller={instance => controller = instance} onChangeList={(items, callback) => { new Promise((resolve, reject) => resolve(setItems(items))) .then(() => callback()) .catch(() => {}); }} defaultValue={value} onChangeItem={item => setValue(item.value)} /> ``` in Class components you can call methods using `this.controller.METHOD_NAME()` and `controller.METHOD_NAME()` in Functional components. 1. Reset the state. You may want to reset the state of your picker. ```javascript this.controller.reset(); ``` 2. Reset items. The second argument is your default value. (Optional) ```javascript this.controller.resetItems([{}, {}, ...]); this.controller.resetItems([{}, {}, ...], 'uk'); // Single this.controller.resetItems([{}, {}, ...], ['uk', ...]); // Multiple ``` 3. Select an item manually. You may want to select an item manually. ```javascript // Single this.controller.selectItem('uk'); // Multiple this.controller.selectItem(['uk', 'france']); ``` 4. Add items manually. There are two methods to help you add items manually. ```javascript this.controller.addItem({ label: 'UK', value: 'uk', icon: () => {}, }); this.controller.addItems([ { label: 'UK', value: 'uk', icon: () => {}, }, ]); ``` 5. Remove items ```javascript this.controller.removeItem('uk', { changeDefaultValue: true, // Unselect if the removed item is the selected item }); ``` 6. Check if the dropdown is open ```javascript this.controller.isOpen(); // boolean ``` 7. Open, close or toggle. ```javascript this.controller.open(); this.controller.close(); this.controller.toggle(); ``` ### Styling The Component There are 14 props to style the component. 1. The `style` property. Use this to adjust the inner part of the picker. ```javacript style={{paddingVertical: 10}} ``` 2. The `dropDownStyle` property. Additional styles for the dropdown box. ```javacript dropDownStyle={{backgroundColor: '#fafafa'}} ``` 3. The `containerStyle` property. Use this to adjust the outer part of the picker such as `margin`, `width`, `height`, `flex`, ... ```javacript containerStyle={{width: 150, height: 70}} ``` 4. The `itemStyle` property. If you want the labels on the `left` and `right` side or to centerize them: ```javacript itemStyle={{justifyContent: 'flex-start|flex-end|center'}} ``` 5. The `labelStyle` property. This property gives full control over the label. ```javacript labelStyle={{ fontSize: 14, textAlign: 'left', color: '#000' }} ``` 6. The `selectedLabelStyle` property. Changes the style of the selected item label. ```javacript selectedLabelStyle={{ color: '#39739d' }} ``` 7. The `placeholderStyle` property. Style the placeholder text with this property. ```javacript placeholderStyle={{ fontWeight: 'bold', textAlign: 'center' }} ``` 8. The `activeItemStyle` property. This property allows you to style the active item. ```javacript activeItemStyle={{justifyContent: 'center'}} ``` 9. The `activeLabelStyle` property. This property allows you to style the active label. ```javacript activeLabelStyle={{color: 'red'}} ``` 10. The `arrowStyle` property. Adds your additional styles to the `View` element of the arrow. ```javacript arrowStyle={{marginRight: 10}} ``` 11. The `searchableStyle` property. Additional styles for the `TextInput` ```javacript searchableStyle={{backgroundColor: '#dfdfdf'}} ``` 12. The `searchablePlaceholderTextColor` property. Assigns a new color to the placeholder text. ```javacript searchablePlaceholderTextColor="silver" ``` 13. The `globalTextStyle` property. You can style `<Text />` elements globally. ```javascript globalTextStyle={{ fontFamily: "MyFontName", fontSize: 15 }} ``` 14. The `childrenContainerStyle` property. Style the children container `View` (See [Category Support](#category-support)) ```javascript childrenContainerStyle={{ paddingLeft: 30 }} ``` ### RTL Support 1. The selected item ![RTL Support](https://raw.githubusercontent.com/hossein-zare/react-native-dropdown-picker/4.x/screenshots/rtl-1.png) ```javascript style={{ flexDirection: 'row-reverse', }} labelStyle={{ textAlign: 'right', }} ``` 2. The dropdown items ![RTL Support](https://raw.githubusercontent.com/hossein-zare/react-native-dropdown-picker/4.x/screenshots/rtl-2.png) ```javascript itemStyle={{ flexDirection: 'row-reverse', justifyContent: 'flex-start', }} ``` ### FAQ #### How to close other pickers when opening another picker? ```javascript this.state = { isVisibleA: false, isVisibleB: false, ... } changeVisibility(state) { this.setState({ isVisibleA: false, isVisibleB: false, ...state }); } // Picker A <DropDownPicker isVisible={this.state.isVisibleA} onOpen={() => this.changeVisibility({ isVisibleA: true })} onClose={() => this.setState({ isVisibleA: false })} ... /> // Picker B <DropDownPicker isVisible={this.state.isVisibleB} onOpen={() => this.changeVisibility({ isVisibleB: true })} onClose={() => this.setState({ isVisibleB: false })} ... /> ``` #### borderRadius Avoid using `borderRadius` and all the corners must be set separately. ```javascript style={{ borderTopLeftRadius: 10, borderTopRightRadius: 10, borderBottomLeftRadius: 10, borderBottomRightRadius: 10 }} dropDownStyle={{ borderBottomLeftRadius: 20, borderBottomRightRadius: 20 }} ``` #### zIndex conflicts (Untouchable Items, Overlapping pickers) 1. Using the `containerStyle` property to style the picker results in unexpected behaviors like untouchable items. > The `style` and `dropDownStyle` properties must be used instead. > Use the `containerStyle` prop to adjust the outer part of the picker such as `margin`, `width`, `height`, `flex`, ... 2. Nested Views > You have to add `zIndex` to the nested views which contain the picker. > **Note!** `zIndex` locks the picker on Android, The solution is to use the `Platform.OS` ```javascript import { Platform } from 'react-native'; <View style={{ ...(Platform.OS !== 'android' && { zIndex: 10 }) }} > <DropDownPicker ... /> </View> ``` Demo: https://snack.expo.io/@hossein-zare/823437 3. DropDownPicker wrapped by `<View style={{backgroundColor: ..., border[...]: ..., elevation: ...}}>` These props will make your dropdown untouchable. Remove all the `backgroundColor`, `border[...]`, `elevation`, ... style properties from the parent element. https://github.com/hossein-zare/react-native-dropdown-picker/issues/40#issuecomment-651744446 4. Multiple Pickers ```javascript <DropDownPicker zIndex={5000} /> <DropDownPicker zIndex={4000} /> <DropDownPicker zIndex={3000} /> ``` #### Dropdown Overflow Adding borders to the component separates elements or may overflow. To solve this issue add `marginTop` to the `dropDownStyle` and specify the value which fits your UI well. ```javascript dropDownStyle={{marginTop: 2}} ``` ### Props | Name | Description | Type | Default | Required | | -------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------- | ------------------------------ | -------- | | **`items`** | The items for the component. | `array` | | Yes | | `defaultValue` | The value of the default item. (If `multiple={true}`, it takes an array of pre-selected values: `['uk']`) | `any` | | No | | `placeholder` | Default text to be shown to the user when `defaultValue={null}` or `defaultValue={[]}` | `string` | 'Select an item' | No | | `dropDownMaxHeight` | Height of the dropdown box. | `number` | `150` | No | | `style` | Additional styles for the picker. | `object` | `{}` | No | | `globalTextStyle` | Global text style.| `object` | `{}` | No | | `dropDownStyle` | Additional styles for the dropdown box. | `object` | `{}` | No | | `containerStyle` | Additional styles for the container view. | `object` | `{}` | No | | `itemStyle` | Additional styles for the items. | `object` | `{}` | No | | `labelStyle` | Additional styles for the labels. | `object` | `{}` | No | | `selectedLabelStyle` | Additional styles for the selected label. | `object` | `{}` | No | | `placeholderStyle` | Additional styles for the placeholder text. | `object` | `{}` | No | | `activeItemStyle` | Additional styles for the active item. | `object` | `{}` | No | | `activeLabelStyle` | Additional styles for the active label. | `object` | `{}` | No | | `arrowStyle` | Additional styles for the arrow. | `object` | `{}` | No | | `arrowColor` | The color of arrow icons | `string` | `#000` | No | | `arrowSize` | The size of the arrow. | `number` | `15` | No | | `showArrow` | An option to show/hide the arrow. | `bool` | `true` | No | | `customArrowUp` | Customize the arrow-up. | `func` | `(size, color) => ...` | No | | `customArrowDown` | Customize the arrow-down. | `func` | `(size, color) => ...` | No | | `customTickIcon` | Customize the tick icon for multiple item picker. | `func` | `() => ...` | No | | `zIndex` | This property specifies the stack order of the component. | `number` | `5000` | No | | `disabled` | Disables the component. | `bool` | `false` | No | | `isVisible` | Open or close the dropdown box. | `bool` | `false` | No | | `autoScrollToDefaultValue` | If true, automatically scroll to `defaultValue`/first `defaultValue` (multiple) during first render of dropdown | `bool` | `false` | No | | `multiple` | If set to true selecting multiple items is possible. | `bool` | `false` | No | | `multipleText` | a Text to inform the user how many items have been selected. | `string` | `%d items have been selected` | No | | `min` | Minimum number of items. | `number` | `0` | No | | `max` | Maximum number of items. | `number` | `10000000` | No | | `searchable` | Shows a `TextInput` to search for specific items. | `bool` | `false` | No | | `searchablePlaceholder` | Default text to be shown to the user. | `string` | `Search for an item` | No | | `searchablePlaceholderTextColor` | TextInput placeholder text color. | `string` | `gray` | No | | `searchableStyle` | Additional styles for the `TextInput` | `object` | `{}` | No | | `searchableError` | Shows a jsx element when nothing found. | `func` | `() => <Text>Not Found</Text>` | No | | `onSearch` | Fires when you type something in the TextInput. | `func` | `(text) => {}` | No | | `selectedLabelLength` | Specify length for the selected label. | `number` | `1000` | No | | `labelLength` | Specify length for the labels. | `number` | `1000` | No | | `labelProps` | Add props to the labels. | `object` | `{}` | No | | `scrollViewProps` | Add props to the `ScrollView` | `object` | `{}` | No | | `searchTextInputProps` | Add props to the search `TextInput` | `object` | `{}` | No | | `containerProps` | Add props to the container view. | `object` | `{}` | No | | `renderSeperator` | Separate items. | `func` | `undefined` | No | | `controller` | Gives you access to the methods and properties. | `func` | `(instance) => {}` | No | | `onOpen` | Fires when you open the picker. | `func` | `() => {}` | No | | `onClose` | Fires when you close the picker. | `func` | `() => {}` | No | | `onChangeItem` | Callback which returns `item` and `index`. The `item` is the selected object or an array of the selected values. | `func` | `(item, index) => {}` | No | | `onChangeList` | Changes the list of items. | `(items, callback) => {}` | No |