react-native-multicolumn-modal-picker
Version:
It is a highly customizable React Native component for the iOS platform. It allows you to configure up to 3 selection columns in the same picker. By default, it can be used as a simple selector.
414 lines (329 loc) • 21.9 kB
Markdown
   
 
This package includes the `@react-native-picker/picker` dependency, which is automatically installed. This allows you to use all functionalities without any additional steps or concerns about this dependency. If you already have this dependency in your project and its version is `2.5.0` or higher, this package will be compatible with it.
This package includes the `prop-types` dependency, which is automatically installed. This allows you to use all functionalities without any additional steps or concerns about this dependency. If you already have this dependency in your project and its version is `15.8.0` or higher, this package will be compatible with it.
This package is compatible with existing React Native projects, whether you’re using `Expo` or pure `React Native`. It has been tested and verified with `react-native` version `0.72.5` and `expo` version `49.0.8`. If you experience any issues when using it with other versions, please feel free to [report it](https://github.com/Rio9735/react-native-multicolumn-modal-picker/issues/new).
`react-native-multicolumn-modal-picker` It is a highly customizable React Native component for the `iOS` platform. It allows you to configure up to 3 selection columns in the same picker. By default, it can be used as a simple selector.
```bash
npm install react-native-multicolumn-modal-picker
```
This command installs the `react-native-multicolumn-modal-picker` package in your current project using `npm`.
```bash
yarn add react-native-multicolumn-modal-picker
```
This command installs the `react-native-multicolumn-modal-picker` package in your current project using `yarn`.
```bash
npx expo install react-native-multicolumn-modal-picker
```
This command is specific for `Expo` projects. It installs the package `react-native-multicolumn-modal-picker` and also automatically handles compatibility with the `Expo` version. It’s important to use this command instead of `npm install` or `yarn add` when you’re working on an `Expo` project.
Currently, this package is optimized for `iOS`. Although it is compatible with `Android`, I decided to restrict its use only to `iOS` as it does not provide a good user experience on `Android`. I’m considering improving this experience and making it fully functional on `Android` too. Your opinion matters to me. Please spare a minute to share your thoughts [here](https://docs.google.com/forms/d/e/1FAIpQLSd3CWTSYT7DJcdCAMP_pE5IG8DrHc0QE2q42jden6JhgyP2PA/viewform?usp=sf_link). Thank you for your patience!
```bash
import MultiColumnModalPicker from 'react-native-multicolumn-modal-picker';
```
You can use the `MultiColumnModalPicker` component in your application as follows:
<p align="center">
<img src="./assets/singleColumnSelector.gif" height="400" />
<img src="./assets/twoColumnSelector.gif" height="400" style="margin-left: 20px;margin-right: 20px" />
<img src="./assets/singleColumnSelectorSearchBar.gif" height="400" />
</p>
```JS
import React, { useState } from "react";
import { View, Button, Text, StyleSheet } from "react-native";
import MultiColumnModalPicker from "react-native-multicolumn-modal-picker";
const App = () => {
const [visible, setVisible] = useState(false);
const [selectedValue, setSelectedValue] = useState(2);
const options = [
{ label: "Option 1", value: 1 },
{ label: "Option 2", value: 2 },
{ label: "Option 3", value: 3 },
];
return (
<View style={styles.container}>
<Text style={styles.title}>
This is an example of a Basic Single Column Picker
</Text>
<Text style={styles.selectedValue}>Selected value: {selectedValue}</Text>
<Button
title="Open selector"
onPress={() => {
setVisible(true);
}}
/>
<MultiColumnModalPicker
visible={visible}
column1={options}
selectedValue1={selectedValue}
onValueChange1={(value) => setSelectedValue(value)}
onClose={() => setVisible(!visible)}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#E6E6E6",
},
title: {
fontSize: 24,
textAlign: "center",
},
selectedValue: {
fontSize: 18,
marginVertical: 10,
},
});
export default App;
```
```JS
import React, { useState } from "react";
import { View, Button, Text, StyleSheet } from "react-native";
import MultiColumnModalPicker from "react-native-multicolumn-modal-picker";
// Component that implements a modal selector with two columns.
const App = () => {
// State variables for the visibility of the selector and the selected hour and minute
const [visible, setVisible] = useState(false);
const [selectedHour, setSelectedHour] = useState(null);
const [selectedMinute, setSelectedMinute] = useState(null);
const [formattedTime, setFormattedTime] = useState("");
// Arrays for the hours and minutes options in the selector
const hours = Array.from({ length: 24 }, (_, i) => ({
label: `${i}`.padStart(2, "0"),
value: `${i}`.padStart(2, "0"),
}));
const minutes = Array.from({ length: 60 }, (_, i) => ({
label: `${i}`.padStart(2, "0"),
value: `${i}`.padStart(2, "0"),
}));
// formatTime function converts the selected hour and minute into a time string.
const formatTime = (hour, minute) => {
let date = new Date();
date.setHours(hour);
date.setMinutes(minute);
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
};
// In this case, action that is executed when pressing outside of the modal, since the accept button is not displayed in the example.
const onAccept = () => {
setFormattedTime(formatTime(selectedHour, selectedMinute));
};
return (
<View style={styles.container}>
<Text style={styles.title}>
This is an example of a Two-Column Picker
</Text>
{formattedTime && (
<Text style={styles.timeText}>
The selected time is: {formattedTime}
</Text>
)}
<Button title="Select Time" onPress={() => setVisible(true)} />
<MultiColumnModalPicker
visible={visible}
actionButtons="cancel"
column1={hours}
column2={minutes}
onValueChange1={(value) => setSelectedHour(value)}
onValueChange2={(value) => setSelectedMinute(value)}
selectedValue1={selectedHour}
selectedValue2={selectedMinute}
onClose={()=> setVisible(false)}
onAccept={onAccept}
// Custom styles
hPadding={80}
bgColor="#097CF6"
selectionHighlightColor="#0024FF"
cancelButtonBgColor="#2E7DD1"
cancelButtonTextStyle={{ color: "#F0F0F0" }}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F0F0F0",
},
title: {
fontSize: 22,
textAlign: "center",
marginBottom: 20,
},
timeText: {
marginBottom: 20,
fontSize: 18,
color: "#333333",
},
});
export default App;
```
```JS
import React, { useCallback, useState } from "react";
import { View, Button, Text, StyleSheet } from "react-native";
import MultiColumnModalPicker from "react-native-multicolumn-modal-picker";
const App = () => {
const [visible, setVisible] = useState(false);
const [selectedValue, setSelectedValue] = useState("+33");
const [selectedCountry, setSelectedCountry] = useState("France");
let options = [
{ label: "Australia", value: "+61" },
{ label: "Argentina", value: "+54" },
{ label: "Brazil", value: "+55" },
{ label: "Croatia", value: "+385" },
{ label: "England", value: "+44" },
{ label: "France", value: "+33" },
{ label: "Japan", value: "+81" },
{ label: "Morocco", value: "+212" },
{ label: "Netherlands", value: "+31" },
{ label: "Poland", value: "+48" },
{ label: "Portugal", value: "+351" },
{ label: "Senegal", value: "+221" },
{ label: "South Korea", value: "+82" },
{ label: "Spain", value: "+34" },
{ label: "Switzerland", value: "+41" },
{ label: "United States", value: "+1" },
];
// Create a mapping object from the values (phone codes) to the labels (country names), especially useful when the array is very large.
const countryByPhoneCode = options.reduce((map, option) => {
map[option.value] = option.label;
return map;
}, {});
// Get the label (country name) from the selected value (phone code).
const getCountry = useCallback(() => {
return countryByPhoneCode[selectedValue];
}, [selectedValue]);
return (
<View style={styles.container}>
<Text style={styles.title}>
This is an example of a Single Column Picker with Search Bar
</Text>
<Text style={styles.selectedValue}>
{selectedCountry} phone code: {selectedValue}
</Text>
<Button
title="Open selector"
onPress={() => {
setVisible(true);
}}
/>
<MultiColumnModalPicker
visible={visible}
searchBar
column1={options}
actionButtons="top"
rightInfo={selectedValue}
onValueChange1={(value) => setSelectedValue(value)}
selectedValue1={selectedValue}
onClose={() => setVisible(false)}
onAccept={() => setSelectedCountry(getCountry())}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#111827",
},
title: {
fontSize: 22,
textAlign: "center",
marginBottom: 20,
color: "#E6E6E6",
},
selectedValue: {
fontSize: 18,
marginVertical: 10,
color: "#E6E6E6",
},
});
export default App;
```
The `MultiColumnModalPicker` component accepts the following props:
| **Required Properties** | **Type** | **Description** | **Usage** |
|-------------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------|
| `visible` | Boolean | Determines whether the modal is visible or not. | visible={visible} |
| `column1` | Array | An array of objects with options for the first column. Each object must have a "label" property and a "value" property. | column1={options} |
| `selectedValue1` | String/Number | The selected value in the first column. | selectedValue1 = {selectedValue} |
| `onValueChange1` | Function | A function that is called when selected value in first column changes. | onValueChange1={(newValue) => setSelectedValue(newValue)} |
| `onClose` | Function | This property is crucial for closing the selector. It’s best to use `onClose` just for closing the modal without adding any extra actions, as it’s used both when **accepting** and **cancelling**. | onClose={() => setVisible(!visible)} |
* `onClose`: _**(Required)**_, _(Function)_ This property is crucial for closing the selector. It’s best to use `onClose` just for closing the modal without adding any extra actions, as it’s used both when **accepting** and **cancelling**.
* `visible`: _**(Required)**_, _(Boolean)_ Determines whether the modal is visible or not.
* `actionButtons` _(Optional)_, _(String)_ Controls the visibility and position of the “Accept” and “Cancel” action buttons. The possible values are:
* `"none"`: No action buttons are displayed. This is the default value.
* `"cancel"`: Only the “Cancel” button is displayed at the bottom.
* `"top"`: Both “Accept” and “Cancel” buttons are displayed at the top.
* `"bottom"`: Both “Accept” and “Cancel” buttons are displayed at the bottom.
* `acceptButtonText`: _(Optional)_, _(String)_ Accept button label. Default is _"Accept"_
* `cancelButtonText`: _(Optional)_, _(String)_ Cancel button label. Default is _"Cancel"_
* `onAccept`: _(Optional)_, _(Function)_ This function is triggered when the user confirms a selection by pressing the accept button or touching outside of the picker. The inherent logical actions are managed automatically. If this function is defined, it will be added to the existing behavior, not overwrite it.
* `onCancel`: _(Optional)_, _(Function)_ A function that is called when the user cancels the selection by pressing the cancel button or the physical back button. The inherent logical actions are managed automatically. If this function is defined, it will be added to the existing behavior, not overwrite it.
* `rightInfo`: _(Optional)_, _(String)_ Text displayed on the right side of the selector. It’s suggested to avoid using with hPadding for best results. This is a guideline, not a rule.
* `title`: _(Optional)_, _(String)_ Title of picker.
* `column1`: _**(Required)**_, _(Array)_ An array of objects with options for first column. Each object must have a ‘label’ property and a ‘value’ property.
* `onValueChange1`: _**(Required)**_, _(Function)_ A function that is called when selected value in first column changes.
* `selectedValue1`: _**(Required)**_, _(String/Number)_ The selected value in first column. Initialization required upon usage.
* `column2`: _(Optional)_, _(Array)_ An array of objects with options for second column. Each object must have a ‘label’ property and a ‘value’ property.
* `onValueChange2`: _**(Required if `column2` is defined)**_, _(Function)_ A function that is called when selected value in second column changes.
* `selectedValue2`: _**(Required if `column2` is defined)**_, _(String/Number)_ The selected value in second column. Initialization required upon usage.
* `column3`: _(Optional)_, _(Array)_ An array of objects with options for third column. Each object must have a ‘label’ property and a ‘value’ property.
* `onValueChange3`: _**(Required if `column3` is defined)**_, _(Function)_ A function that is called when selected value in third column changes.
* `selectedValue3`: _**(Required if `column3` is defined)**_, _(String/Number)_ The selected value in third column. Initialization required upon usage.
* `searchBar`: _(Optional)_,_(Boolean)_ Indicates whether the search bar is displayed or not. _**(Please note that the search bar can only be used when the selector has a single column, specifically with `column1`.)**_
* `searchBoxStyle`: _(Optional)_,_(JSX style object)_ Determines the style of the search bar. Accepts standard React Native style properties.
* `searchPlaceholder`: _(Optional)_,_(String)_ Placeholder of the search bar. The default value is "Search here".
* `searchElementsColor`: _(Optional)_, _(String)_ Defines the color of both the search bar placeholder and the clear button within the search bar. Accepts standard React Native color values.
* `searchTextStyle`: _(Optional)_,_(JSX style object)_ Determines the text style of the search bar. Accepts standard React Native style properties.
* `acceptButtonTextStyle`: _(Optional)_, _(JSX style object)_ Style of the accept button text. Accepts standard React Native style properties.
* `actionButtonsBorderColor`: _(Optional)_, _(String)_ This property sets the border color of the action buttons. It is only applicable when `actionButtons` is set to `“top”` or `“bottom”`. Accepts standard React Native color values.
* `bgColor`: _(Optional)_, _(String)_ Background color of modal. Accepts standard React Native color values.
* `cancelButtonBgColor`: _(Optional)_, _(String)_ This property sets the background color of the “cancel button” that appears at the bottom of the picker. Accepts standard React Native color values.
* `cancelButtonTextStyle`: _(Optional)_, _(JSX style object)_ Style of the cancel button text. Accepts standard React Native style properties.
* `hPadding`: _(Optional)_, _(Number > 0)_ Adds extra horizontal space around the picker.
* `itemStyle`: _(Optional)_, _(JSX style object)_ Style of the picker items. Accepts standard React Native style properties.
* `rightInfoTextStyle`: _(Optional)_, _(JSX style object)_ Style of text for additional information to right side of modal. Accepts standard React Native style properties.
* `selectionHighlightColor`: _(Optional)_, _(String)_ Color of the selection highlight. Accepts standard React Native color values.
* `titleStyle`: _(Optional)_, _(JSX style object)_ Style of the title text. Accepts standard React Native style properties.
Contributions are welcome to `react-native-multicolumn-modal-picker`.
If you have an idea for a new feature or have discovered a bug, please open an [issue](https://github.com/Rio9735/react-native-multicolumn-modal-picker/issues/new) or participate in a [discussion](https://github.com/Rio9735/react-native-multicolumn-modal-picker/discussions/1).
Don't forget to add a **title** and a **description** explaining the issue you're trying to solve and your proposed solution.
Screenshots or gifs are helpful to add to the repository for reviews.
Thank you for using my package! Your support is greatly appreciated and it motivates me to continue improving and adding new features. If you find my package useful, please consider giving it a :star: on GitHub. This lets me know that I’m on the right track and encourages me to keep going.
[](https://github.com/Rio9735/react-native-multicolumn-modal-picker)
For a detailed list of changes in each version, please refer to the [CHANGELOG](./CHANGELOG.md)
_**Río**_
Feel free to [Contact me](mailto:markidelrio@gmail.com).
The library is released under the MIT license. For more details see [LICENSE](./LICENSE)