diff --git a/README.md b/README.md
index 7388049..37c2081 100644
--- a/README.md
+++ b/README.md
@@ -5,31 +5,30 @@

## Add it to your project
- - Using NPM
- `npm install react-native-select-two`
- - or:
- - Using Yarn
- `yarn add react-native-select-two`
+- Using NPM
+ `npm install react-native-select-two`
+- or:
+- Using Yarn
+ `yarn add react-native-select-two`
## Install dependencies
1. [react-native-modal](https://github.com/react-native-community/react-native-modal)
2. [react-native-vector-icons](https://github.com/oblador/react-native-vector-icons)
-
## Usage
```javascript
-import React, { Component } from "react"
-import { View, Text, StyleSheet } from "react-native"
-import Select2 from "react-native-select-two"
+import React, { Component } from "react";
+import { View, Text, StyleSheet } from "react-native";
+import Select2 from "react-native-select-two";
const mockData = [
{ id: 1, name: "React Native Developer", checked: true }, // set default checked for render option item
{ id: 2, name: "Android Developer" },
- { id: 3, name: "iOS Developer" }
-]
+ { id: 3, name: "iOS Developer" },
+];
// create a component
class CreateNewAppointment extends Component {
@@ -43,15 +42,15 @@ class CreateNewAppointment extends Component {
popupTitle="Select item"
title="Select item"
data={mockData}
- onSelect={data => {
- this.setState({ data })
+ onSelect={(data) => {
+ this.setState({ data });
}}
- onRemoveItem={data => {
- this.setState({ data })
+ onRemoveItem={(data) => {
+ this.setState({ data });
}}
/>
- )
+ );
}
}
```
@@ -65,6 +64,8 @@ class CreateNewAppointment extends Component {
| Property name | Type | Default | Description |
| ------------------------- | -------------- | ------------------------------- | ------------------------------------------------------------------------------------------- |
| **style** | _Object_ | none | Custom style for component |
+| **tagStyle** | _Object_ | none | Custom style for tag component |
+| **tagTextStyle** | _Object_ | none | Custom style for text component inside tag component |
| **modalStyle** | _Object_ | none | Custom style for modal |
| **title** | _String_ | none | String display when you don't select any item |
| **data** | _Array_ | \*required | Datasource of list options: an array of objects (each object have `name` and `id` property) |
diff --git a/index.js b/index.js
index 5c94a58..c6ff223 100644
--- a/index.js
+++ b/index.js
@@ -1,330 +1,449 @@
//import liraries
-import React, { Component } from 'react';
-import { Text, StyleSheet, TouchableOpacity, View, FlatList, TextInput, Dimensions, Animated, Platform } from 'react-native';
-import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
-import Modal from 'react-native-modal';
-import Button from './lib/Button';
-import TagItem from './lib/TagItem';
-import utilities from './lib/utilities';
-import PropTypes from 'prop-types';
+import React, { Component } from "react";
+import {
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ View,
+ FlatList,
+ TextInput,
+ Dimensions,
+ Animated,
+ Platform,
+} from "react-native";
+import Icon from "react-native-vector-icons/MaterialCommunityIcons";
+import Modal from "react-native-modal";
+import Button from "./lib/Button";
+import TagItem from "./lib/TagItem";
+import utilities from "./lib/utilities";
+import PropTypes from "prop-types";
-const { height } = Dimensions.get('window');
+const { height } = Dimensions.get("window");
const INIT_HEIGHT = height * 0.6;
// create a component
class Select2 extends Component {
- static defaultProps = {
- cancelButtonText: 'Hủy',
- selectButtonText: 'Chọn',
- searchPlaceHolderText: "Nhập vào từ khóa",
- listEmptyTitle: 'Không tìm thấy lựa chọn phù hợp',
- colorTheme: '#16a45f',
- buttonTextStyle: {},
- buttonStyle: {},
- showSearchBox: true
- }
- state = {
- show: false,
- preSelectedItem: [],
- selectedItem: [],
- data: [],
- keyword: ''
- }
- animatedHeight = new Animated.Value(INIT_HEIGHT);
+ static defaultProps = {
+ cancelButtonText: "Hủy",
+ selectButtonText: "Chọn",
+ searchPlaceHolderText: "Nhập vào từ khóa",
+ listEmptyTitle: "Không tìm thấy lựa chọn phù hợp",
+ colorTheme: "#16a45f",
+ buttonTextStyle: {},
+ buttonStyle: {},
+ showSearchBox: true,
+ };
+ state = {
+ show: false,
+ preSelectedItem: [],
+ selectedItem: [],
+ data: [],
+ keyword: "",
+ };
+ animatedHeight = new Animated.Value(INIT_HEIGHT);
- componentDidMount() {
- this.init();
- };
+ componentDidMount() {
+ this.init();
+ }
- UNSAFE_componentWillReceiveProps(newProps) {
- this.init(newProps);
- }
+ UNSAFE_componentWillReceiveProps(newProps) {
+ this.init(newProps);
+ }
- init(newProps) {
- let preSelectedItem = [];
- let { data } = newProps || this.props;
- data.map(item => {
- if (item.checked) {
- preSelectedItem.push(item);
- }
- })
- this.setState({ data, preSelectedItem });
- }
+ init(newProps) {
+ let preSelectedItem = [];
+ let { data } = newProps || this.props;
+ data.map((item) => {
+ if (item.checked) {
+ preSelectedItem.push(item);
+ }
+ });
+ this.setState({ data, preSelectedItem });
+ }
- get dataRender() {
- let { data, keyword } = this.state;
- let listMappingKeyword = [];
- data.map(item => {
- if (utilities.changeAlias(item.name).includes(utilities.changeAlias(keyword))) {
- listMappingKeyword.push(item);
- }
- });
- return listMappingKeyword;
- }
+ get dataRender() {
+ let { data, keyword } = this.state;
+ let listMappingKeyword = [];
+ data.map((item) => {
+ if (
+ utilities
+ .changeAlias(item.name)
+ .includes(utilities.changeAlias(keyword))
+ ) {
+ listMappingKeyword.push(item);
+ }
+ });
+ return listMappingKeyword;
+ }
- get defaultFont() {
- let { defaultFontName } = this.props;
- return defaultFontName ? { fontFamily: defaultFontName } : {};
- }
+ get defaultFont() {
+ let { defaultFontName } = this.props;
+ return defaultFontName ? { fontFamily: defaultFontName } : {};
+ }
- cancelSelection() {
- let { data, preSelectedItem } = this.state;
- data.map(item => {
- item.checked = false;
- for (let _selectedItem of preSelectedItem) {
- if (item.id === _selectedItem.id) {
- item.checked = true;
- break;
- }
- }
- });
- this.setState({ data, show: false, keyword: '', selectedItem: preSelectedItem });
- }
-
- onItemSelected = (item, isSelectSingle) => {
- let selectedItem = [];
- let { data } = this.state;
- item.checked = !item.checked;
- for (let index in data) {
- if (data[index].id === item.id) {
- data[index] = item;
- } else if (isSelectSingle) {
- data[index].checked = false;
- }
+ cancelSelection() {
+ let { data, preSelectedItem } = this.state;
+ data.map((item) => {
+ item.checked = false;
+ for (let _selectedItem of preSelectedItem) {
+ if (item.id === _selectedItem.id) {
+ item.checked = true;
+ break;
}
- data.map(item => {
- if (item.checked) selectedItem.push(item);
- })
- this.setState({ data, selectedItem });
- }
- keyExtractor = (item, idx) => idx.toString();
- renderItem = ({ item, idx }) => {
- let { colorTheme, isSelectSingle } = this.props;
- return (
- this.onItemSelected(item, isSelectSingle)}
- activeOpacity={0.7}
- style={styles.itemWrapper}>
-
- {item.name}
-
-
-
- );
- }
- renderEmpty = () => {
- let { listEmptyTitle } = this.props;
- return (
-
- {listEmptyTitle}
-
- );
+ }
+ });
+ this.setState({
+ data,
+ show: false,
+ keyword: "",
+ selectedItem: preSelectedItem,
+ });
+ }
+
+ onItemSelected = (item, isSelectSingle) => {
+ let selectedItem = [];
+ let { data } = this.state;
+ item.checked = !item.checked;
+ for (let index in data) {
+ if (data[index].id === item.id) {
+ data[index] = item;
+ } else if (isSelectSingle) {
+ data[index].checked = false;
+ }
}
- closeModal = () => this.setState({ show: false });
- showModal = () => this.setState({ show: true });
+ data.map((item) => {
+ if (item.checked) selectedItem.push(item);
+ });
+ this.setState({ data, selectedItem });
+ };
+ keyExtractor = (item, idx) => idx.toString();
+ renderItem = ({ item, idx }) => {
+ let { colorTheme, isSelectSingle } = this.props;
+ return (
+ this.onItemSelected(item, isSelectSingle)}
+ activeOpacity={0.7}
+ style={styles.itemWrapper}
+ >
+ {item.name}
+
+
+ );
+ };
+ renderEmpty = () => {
+ let { listEmptyTitle } = this.props;
+ return (
+ {listEmptyTitle}
+ );
+ };
+ closeModal = () => this.setState({ show: false });
+ showModal = () => this.setState({ show: true });
- render() {
- let {
- style, modalStyle, title, onSelect, onRemoveItem, popupTitle, colorTheme,
- isSelectSingle, cancelButtonText, selectButtonText, searchPlaceHolderText,
- selectedTitleStyle, buttonTextStyle, buttonStyle, showSearchBox
- } = this.props;
- let { show, selectedItem, preSelectedItem } = this.state;
- return (
-
-
-
-
-
- {popupTitle || title}
-
-
-
- {
- showSearchBox
- ? this.setState({ keyword })}
- onFocus={() => {
- Animated.spring(this.animatedHeight, {
- toValue: INIT_HEIGHT + (Platform.OS === 'ios' ? height * 0.2 : 0),
- friction: 7
- }).start();
- }}
- onBlur={() => {
- Animated.spring(this.animatedHeight, {
- toValue: INIT_HEIGHT,
- friction: 7
- }).start();
- }}
- />
- : null
- }
-
+ render() {
+ let {
+ style,
+ modalStyle,
+ title,
+ onSelect,
+ onRemoveItem,
+ popupTitle,
+ colorTheme,
+ isSelectSingle,
+ cancelButtonText,
+ selectButtonText,
+ searchPlaceHolderText,
+ selectedTitleStyle,
+ buttonTextStyle,
+ buttonStyle,
+ showSearchBox,
+ tagStyle,
+ tagTextStyle,
+ } = this.props;
+ let { show, selectedItem, preSelectedItem } = this.state;
+ return (
+
+
+
+
+
+ {popupTitle || title}
+
+
+
+ {showSearchBox ? (
+ this.setState({ keyword })}
+ onFocus={() => {
+ Animated.spring(this.animatedHeight, {
+ toValue:
+ INIT_HEIGHT + (Platform.OS === "ios" ? height * 0.2 : 0),
+ friction: 7,
+ }).start();
+ }}
+ onBlur={() => {
+ Animated.spring(this.animatedHeight, {
+ toValue: INIT_HEIGHT,
+ friction: 7,
+ }).start();
+ }}
+ />
+ ) : null}
+
-
-
-
-
- {
- preSelectedItem.length > 0
- ? (
- isSelectSingle
- ? {preSelectedItem[0].name}
- :
- {
- preSelectedItem.map((tag, index) => {
- return (
- {
- let preSelectedItem = [];
- let selectedIds = [], selectedObjectItems = [];
- let { data } = this.state;
- data.map(item => {
- if (item.id === tag.id) {
- item.checked = false;
- }
- if (item.checked) {
- preSelectedItem.push(item);
- selectedIds.push(item.id);
- selectedObjectItems.push(item);
- };
- })
- this.setState({ data, preSelectedItem });
- onRemoveItem && onRemoveItem(selectedIds, selectedObjectItems);
- }}
- tagName={tag.name} />
- );
- })
- }
-
- )
- : {title}
- }
-
- );
- }
+
+ {
+ this.cancelSelection();
+ }}
+ title={cancelButtonText}
+ textColor={colorTheme}
+ backgroundColor="#fff"
+ textStyle={buttonTextStyle}
+ style={[
+ styles.button,
+ buttonStyle,
+ {
+ marginRight: 5,
+ marginLeft: 10,
+ borderWidth: 1,
+ borderColor: colorTheme,
+ },
+ ]}
+ />
+ {
+ let selectedIds = [],
+ selectedObjectItems = [];
+ selectedItem.map((item) => {
+ selectedIds.push(item.id);
+ selectedObjectItems.push(item);
+ });
+ onSelect && onSelect(selectedIds, selectedObjectItems);
+ this.setState({
+ show: false,
+ keyword: "",
+ preSelectedItem: selectedItem,
+ });
+ }}
+ title={selectButtonText}
+ backgroundColor={colorTheme}
+ textStyle={buttonTextStyle}
+ style={[
+ styles.button,
+ buttonStyle,
+ { marginLeft: 5, marginRight: 10 },
+ ]}
+ />
+
+
+
+ {preSelectedItem.length > 0 ? (
+ isSelectSingle ? (
+
+ {preSelectedItem[0].name}
+
+ ) : (
+
+ {preSelectedItem.map((tag, index) => {
+ return (
+ {
+ let preSelectedItem = [];
+ let selectedIds = [],
+ selectedObjectItems = [];
+ let { data } = this.state;
+ data.map((item) => {
+ if (item.id === tag.id) {
+ item.checked = false;
+ }
+ if (item.checked) {
+ preSelectedItem.push(item);
+ selectedIds.push(item.id);
+ selectedObjectItems.push(item);
+ }
+ });
+ this.setState({ data, preSelectedItem });
+ onRemoveItem &&
+ onRemoveItem(selectedIds, selectedObjectItems);
+ }}
+ tagName={tag.name}
+ />
+ );
+ })}
+
+ )
+ ) : (
+
+ {title}
+
+ )}
+
+ );
+ }
}
// define your styles
const styles = StyleSheet.create({
- container: {
- width: '100%', minHeight: 45, borderRadius: 2, paddingHorizontal: 16,
- flexDirection: 'row', alignItems: 'center', borderWidth: 1,
- borderColor: '#cacaca', paddingVertical: 4
- },
- modalContainer: {
- paddingTop: 16, backgroundColor: '#fff', borderTopLeftRadius: 8, borderTopRightRadius: 8
- },
- title: {
- fontSize: 16, marginBottom: 16, width: '100%', textAlign: 'center'
- },
- line: {
- height: 1, width: '100%', backgroundColor: '#cacaca'
- },
- inputKeyword: {
- height: 40, borderRadius: 5, borderWidth: 1, borderColor: '#cacaca',
- paddingLeft: 8, marginHorizontal: 24, marginTop: 16
- },
- buttonWrapper: {
- marginVertical: 16, flexDirection: 'row', alignItems: 'center', justifyContent: 'center'
- },
- button: {
- height: 36, flex: 1
- },
- selectedTitlte: {
- fontSize: 14, color: 'gray', flex: 1
- },
- tagWrapper: {
- flexDirection: 'row', flexWrap: 'wrap'
- },
- listOption: {
- paddingHorizontal: 24,
- paddingTop: 1, marginTop: 16
- },
- itemWrapper: {
- borderBottomWidth: 1, borderBottomColor: '#eaeaea',
- paddingVertical: 12, flexDirection: 'row', alignItems: 'center'
- },
- itemText: {
- fontSize: 16, color: '#333', flex: 1
- },
- itemIcon: {
- width: 30, textAlign: 'right'
- },
- empty: {
- fontSize: 16, color: 'gray', alignSelf: 'center', textAlign: 'center', paddingTop: 16
- }
+ container: {
+ width: "100%",
+ minHeight: 45,
+ borderRadius: 2,
+ paddingHorizontal: 16,
+ flexDirection: "row",
+ alignItems: "center",
+ borderWidth: 1,
+ borderColor: "#cacaca",
+ paddingVertical: 4,
+ },
+ modalContainer: {
+ paddingTop: 16,
+ backgroundColor: "#fff",
+ borderTopLeftRadius: 8,
+ borderTopRightRadius: 8,
+ },
+ title: {
+ fontSize: 16,
+ marginBottom: 16,
+ width: "100%",
+ textAlign: "center",
+ },
+ line: {
+ height: 1,
+ width: "100%",
+ backgroundColor: "#cacaca",
+ },
+ inputKeyword: {
+ height: 40,
+ borderRadius: 5,
+ borderWidth: 1,
+ borderColor: "#cacaca",
+ paddingLeft: 8,
+ marginHorizontal: 24,
+ marginTop: 16,
+ },
+ buttonWrapper: {
+ marginVertical: 16,
+ flexDirection: "row",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ button: {
+ height: 36,
+ flex: 1,
+ },
+ selectedTitlte: {
+ fontSize: 14,
+ color: "gray",
+ flex: 1,
+ },
+ tagWrapper: {
+ flexDirection: "row",
+ flexWrap: "wrap",
+ },
+ listOption: {
+ paddingHorizontal: 24,
+ paddingTop: 1,
+ marginTop: 16,
+ },
+ itemWrapper: {
+ borderBottomWidth: 1,
+ borderBottomColor: "#eaeaea",
+ paddingVertical: 12,
+ flexDirection: "row",
+ alignItems: "center",
+ },
+ itemText: {
+ fontSize: 16,
+ color: "#333",
+ flex: 1,
+ },
+ itemIcon: {
+ width: 30,
+ textAlign: "right",
+ },
+ empty: {
+ fontSize: 16,
+ color: "gray",
+ alignSelf: "center",
+ textAlign: "center",
+ paddingTop: 16,
+ },
});
Select2.propTypes = {
- data: PropTypes.array.isRequired,
- style: PropTypes.object,
- defaultFontName: PropTypes.string,
- selectedTitleStyle: PropTypes.object,
- buttonTextStyle: PropTypes.object,
- buttonStyle: PropTypes.object,
- title: PropTypes.string,
- onSelect: PropTypes.func,
- onRemoveItem: PropTypes.func,
- popupTitle: PropTypes.string,
- colorTheme: PropTypes.string,
- isSelectSingle: PropTypes.bool,
- showSearchBox: PropTypes.bool,
- cancelButtonText: PropTypes.string,
- selectButtonText: PropTypes.string
-}
+ data: PropTypes.array.isRequired,
+ style: PropTypes.object,
+ defaultFontName: PropTypes.string,
+ selectedTitleStyle: PropTypes.object,
+ buttonTextStyle: PropTypes.object,
+ buttonStyle: PropTypes.object,
+ title: PropTypes.string,
+ onSelect: PropTypes.func,
+ onRemoveItem: PropTypes.func,
+ popupTitle: PropTypes.string,
+ colorTheme: PropTypes.string,
+ isSelectSingle: PropTypes.bool,
+ showSearchBox: PropTypes.bool,
+ cancelButtonText: PropTypes.string,
+ selectButtonText: PropTypes.string,
+};
//make this component available to the app
export default Select2;
diff --git a/lib/TagItem.js b/lib/TagItem.js
index c24a409..8634cba 100644
--- a/lib/TagItem.js
+++ b/lib/TagItem.js
@@ -1,23 +1,36 @@
-import React from 'react';
-import {TouchableOpacity, Text } from 'react-native';
-import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
+import React from "react";
+import { TouchableOpacity, Text } from "react-native";
+import Icon from "react-native-vector-icons/MaterialCommunityIcons";
-const TagItem = ({ tagName, onRemoveTag }) => {
- return (
-
-
-
- {tagName}
-
-
- );
-}
-export default TagItem;
\ No newline at end of file
+const TagItem = ({ tagName, onRemoveTag, tagStyle, tagTextStyle }) => {
+ return (
+
+
+
+ {tagName}
+
+
+ );
+};
+export default TagItem;