diff --git a/README.md b/README.md
index f863606..40feffc 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,66 @@
+# Support SectionList in dropdown list
+
+You just need to format your data as for a SectionList and add the "renderSectionHeader" porps
+
+```javascript
+const options = [
+ {
+ title: 'Pizza',
+ data: [
+ {
+ key: 'pizza1',
+ name: 'Name of Pizza n°1',
+ },
+ {
+ key: 'pizza2',
+ name: 'Name of Pizza n°2',
+ },
+ {
+ key: 'pizza3',
+ name: 'Name of Pizza n°3',
+ },
+ ],
+ },
+ {
+ title: 'Burger',
+ data: [
+ {
+ key: 'burger1',
+ name: 'Name of Burger n°1',
+ },
+ {
+ key: 'burger2',
+ name: 'Name of Burger n°2',
+ },
+ {
+ key: 'burger3',
+ name: 'Name of Burger n°3',
+ },
+ ],
+ },
+];
+```
+
+```javascript
+renderHeader = ({ section: { title } }) => (
+
+ {title}
+
+)
+```
+
+```javascript
+
+```
+
+# After it's same of fork
+
[](https://badge.fury.io/js/react-native-modal-dropdown)
# react-native-modal-dropdown
diff --git a/components/ModalDropdown.js b/components/ModalDropdown.js
index ace1472..51be436 100644
--- a/components/ModalDropdown.js
+++ b/components/ModalDropdown.js
@@ -1,13 +1,4 @@
-/**
- * Created by sohobloo on 16/9/13.
- */
-
-'use strict';
-
-import React, {
- Component,
-} from 'react';
-
+import React, { Component } from 'react';
import {
StyleSheet,
Dimensions,
@@ -19,78 +10,93 @@ import {
TouchableHighlight,
Modal,
ActivityIndicator,
+ FlatList,
+ SectionList,
} from 'react-native';
-
-import ListView from "deprecated-react-native-listview";
import PropTypes from 'prop-types';
-
const TOUCHABLE_ELEMENTS = [
'TouchableHighlight',
'TouchableOpacity',
'TouchableWithoutFeedback',
- 'TouchableNativeFeedback'
+ 'TouchableNativeFeedback',
];
-
export default class ModalDropdown extends Component {
static propTypes = {
disabled: PropTypes.bool,
scrollEnabled: PropTypes.bool,
defaultIndex: PropTypes.number,
+ selected: PropTypes.string,
defaultValue: PropTypes.string,
- options: PropTypes.array,
-
+ selectByKey: PropTypes.string,
+ options: PropTypes.array.isRequired,
accessible: PropTypes.bool,
animated: PropTypes.bool,
showsVerticalScrollIndicator: PropTypes.bool,
keyboardShouldPersistTaps: PropTypes.string,
-
- style: PropTypes.oneOfType([PropTypes.number, PropTypes.object, PropTypes.array]),
- textStyle: PropTypes.oneOfType([PropTypes.number, PropTypes.object, PropTypes.array]),
- dropdownStyle: PropTypes.oneOfType([PropTypes.number, PropTypes.object, PropTypes.array]),
- dropdownTextStyle: PropTypes.oneOfType([PropTypes.number, PropTypes.object, PropTypes.array]),
- dropdownTextHighlightStyle: PropTypes.oneOfType([PropTypes.number, PropTypes.object, PropTypes.array]),
-
+ style: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.object,
+ PropTypes.array,
+ ]),
+ textStyle: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.object,
+ PropTypes.array,
+ ]),
+ dropdownStyle: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.object,
+ PropTypes.array,
+ ]),
+ dropdownTextStyle: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.object,
+ PropTypes.array,
+ ]),
+ dropdownTextHighlightStyle: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.object,
+ PropTypes.array,
+ ]),
adjustFrame: PropTypes.func,
renderRow: PropTypes.func,
renderSeparator: PropTypes.func,
+ renderSectionHeader: PropTypes.func,
renderButtonText: PropTypes.func,
-
onDropdownWillShow: PropTypes.func,
onDropdownWillHide: PropTypes.func,
- onSelect: PropTypes.func
+ onSelect: PropTypes.func,
};
-
static defaultProps = {
disabled: false,
scrollEnabled: true,
+ selected: null,
+ selectByKey: null,
defaultIndex: -1,
defaultValue: 'Please select...',
options: null,
animated: true,
+ renderSectionHeader: null,
showsVerticalScrollIndicator: true,
- keyboardShouldPersistTaps: 'never'
+ keyboardShouldPersistTaps: 'never',
};
-
constructor(props) {
super(props);
-
this._button = null;
this._buttonFrame = null;
this._nextValue = null;
this._nextIndex = null;
-
this.state = {
accessible: !!props.accessible,
loading: !props.options,
showDropdown: false,
- buttonText: props.defaultValue,
- selectedIndex: props.defaultIndex
+ buttonText: props.selectByKey ? props.selected : props.defaultValue,
+ selectedIndex: props.selectByKey ? props.selected : props.defaultIndex,
};
}
-
- componentWillReceiveProps(nextProps) {
- let {buttonText, selectedIndex} = this.state;
- const {defaultIndex, defaultValue, options} = nextProps;
+ static getDerivedStateFromProps(props, state) {
+ let { buttonText, selectedIndex } = state;
+ const { defaultIndex, defaultValue, options } = props;
buttonText = this._nextValue == null ? buttonText : this._nextValue;
selectedIndex = this._nextIndex == null ? selectedIndex : this._nextIndex;
if (selectedIndex < 0) {
@@ -101,117 +107,111 @@ export default class ModalDropdown extends Component {
}
this._nextValue = null;
this._nextIndex = null;
-
- this.setState({
+ return {
loading: !options,
buttonText,
- selectedIndex
- });
- }
-
- render() {
- return (
-
- {this._renderButton()}
- {this._renderModal()}
-
- );
+ selectedIndex,
+ }
}
-
_updatePosition(callback) {
if (this._button && this._button.measure) {
this._button.measure((fx, fy, width, height, px, py) => {
- this._buttonFrame = {x: px, y: py, w: width, h: height};
+ this._buttonFrame = {
+ x: px,
+ y: py,
+ w: width,
+ h: height,
+ };
callback && callback();
});
}
}
-
show() {
this._updatePosition(() => {
this.setState({
- showDropdown: true
+ showDropdown: true,
});
});
}
-
hide() {
this.setState({
- showDropdown: false
+ showDropdown: false,
});
}
-
select(idx) {
- const {defaultValue, options, defaultIndex, renderButtonText} = this.props;
-
+ const {
+ defaultValue,
+ options,
+ defaultIndex,
+ renderButtonText,
+ selectByKey,
+ } = this.props;
let value = defaultValue;
if (idx == null || !options || idx >= options.length) {
idx = defaultIndex;
}
-
if (idx >= 0) {
- value = renderButtonText ? renderButtonText(options[idx]) : options[idx].toString();
+ value = renderButtonText
+ ? renderButtonText(options[idx])
+ : options[idx].toString();
}
-
this._nextValue = value;
this._nextIndex = idx;
-
this.setState({
- buttonText: value,
- selectedIndex: idx
+ buttonText: selectByKey ? options[idx][selectByKey] : value,
+ selectedIndex: idx,
});
}
-
_renderButton() {
- const {disabled, accessible, children, textStyle} = this.props;
- const {buttonText} = this.state;
-
+ const { disabled, accessible, children, textStyle } = this.props;
+ const { buttonText } = this.state;
return (
- this._button = button}
- disabled={disabled}
- accessible={accessible}
- onPress={this._onButtonPress}
+ (this._button = button)}
+ disabled={disabled}
+ accessible={accessible}
+ onPress={this._onButtonPress}
>
- {
- children ||
- (
-
-
- {buttonText}
-
-
- )
- }
+ {children || (
+
+
+ {buttonText}
+
+
+ )}
);
}
-
_onButtonPress = () => {
- const {onDropdownWillShow} = this.props;
- if (!onDropdownWillShow ||
- onDropdownWillShow() !== false) {
+ const { onDropdownWillShow } = this.props;
+ if (!onDropdownWillShow || onDropdownWillShow() !== false) {
this.show();
}
};
-
_renderModal() {
- const {animated, accessible, dropdownStyle} = this.props;
- const {showDropdown, loading} = this.state;
+ const { animated, accessible, dropdownStyle } = this.props;
+ const { showDropdown, loading } = this.state;
if (showDropdown && this._buttonFrame) {
const frameStyle = this._calcPosition();
const animationType = animated ? 'fade' : 'none';
return (
-
-
@@ -223,126 +223,132 @@ export default class ModalDropdown extends Component {
);
}
}
-
_calcPosition() {
- const {dropdownStyle, style, adjustFrame} = this.props;
-
+ const { dropdownStyle, style, adjustFrame } = this.props;
const dimensions = Dimensions.get('window');
const windowWidth = dimensions.width;
const windowHeight = dimensions.height;
-
- const dropdownHeight = (dropdownStyle && StyleSheet.flatten(dropdownStyle).height) ||
+ const dropdownHeight =
+ (dropdownStyle && StyleSheet.flatten(dropdownStyle).height) ||
StyleSheet.flatten(styles.dropdown).height;
-
- const bottomSpace = windowHeight - this._buttonFrame.y - this._buttonFrame.h;
+ const bottomSpace =
+ windowHeight - this._buttonFrame.y - this._buttonFrame.h;
const rightSpace = windowWidth - this._buttonFrame.x;
- const showInBottom = bottomSpace >= dropdownHeight || bottomSpace >= this._buttonFrame.y;
+ const showInBottom =
+ bottomSpace >= dropdownHeight || bottomSpace >= this._buttonFrame.y;
const showInLeft = rightSpace >= this._buttonFrame.x;
-
const positionStyle = {
height: dropdownHeight,
- top: showInBottom ? this._buttonFrame.y + this._buttonFrame.h : Math.max(0, this._buttonFrame.y - dropdownHeight),
+ top: showInBottom
+ ? this._buttonFrame.y + this._buttonFrame.h
+ : Math.max(0, this._buttonFrame.y - dropdownHeight),
};
-
if (showInLeft) {
positionStyle.left = this._buttonFrame.x;
} else {
- const dropdownWidth = (dropdownStyle && StyleSheet.flatten(dropdownStyle).width) ||
- (style && StyleSheet.flatten(style).width) || -1;
+ const dropdownWidth =
+ (dropdownStyle && StyleSheet.flatten(dropdownStyle).width) ||
+ (style && StyleSheet.flatten(style).width) ||
+ -1;
if (dropdownWidth !== -1) {
positionStyle.width = dropdownWidth;
}
positionStyle.right = rightSpace - this._buttonFrame.w;
}
-
return adjustFrame ? adjustFrame(positionStyle) : positionStyle;
}
-
_onRequestClose = () => {
- const {onDropdownWillHide} = this.props;
- if (!onDropdownWillHide ||
- onDropdownWillHide() !== false) {
+ const { onDropdownWillHide } = this.props;
+ if (!onDropdownWillHide || onDropdownWillHide() !== false) {
this.hide();
}
};
-
_onModalPress = () => {
- const {onDropdownWillHide} = this.props;
- if (!onDropdownWillHide ||
- onDropdownWillHide() !== false) {
+ const { onDropdownWillHide } = this.props;
+ if (!onDropdownWillHide || onDropdownWillHide() !== false) {
this.hide();
}
};
-
- _renderLoading() {
- return (
-
- );
- }
-
+ _renderLoading = () => {
+ return ;
+ };
_renderDropdown() {
- const {scrollEnabled, renderSeparator, showsVerticalScrollIndicator, keyboardShouldPersistTaps} = this.props;
+ const {
+ scrollEnabled,
+ renderSeparator,
+ showsVerticalScrollIndicator,
+ keyboardShouldPersistTaps,
+ options,
+ renderSectionHeader,
+ } = this.props;
+ const props = {
+ data: options,
+ scrollEnabled: scrollEnabled,
+ style: styles.list,
+ keyExtractor: (item, i) => (`key-${i}`),
+ renderItem: this._renderItem,
+ ItemSeparatorComponent: renderSeparator || this._renderSeparator,
+ automaticallyAdjustContentInsets: false,
+ showsVerticalScrollIndicator: showsVerticalScrollIndicator,
+ keyboardShouldPersistTaps: keyboardShouldPersistTaps,
+ }
+ if (renderSectionHeader) {
+ return (
+
+ );
+ }
return (
-
+
);
}
-
- get _dataSource() {
- const {options} = this.props;
- const ds = new ListView.DataSource({
- rowHasChanged: (r1, r2) => r1 !== r2
- });
- return ds.cloneWithRows(options);
- }
-
- _renderRow = (rowData, sectionID, rowID, highlightRow) => {
- const {renderRow, dropdownTextStyle, dropdownTextHighlightStyle, accessible} = this.props;
- const {selectedIndex} = this.state;
- const key = `row_${rowID}`;
- const highlighted = rowID == selectedIndex;
- const row = !renderRow ?
- ( {
+ const {
+ renderRow,
+ dropdownTextStyle,
+ dropdownTextHighlightStyle,
+ accessible,
+ selectByKey,
+ selected,
+ } = this.props;
+ const { selectedIndex } = this.state;
+ const selector = selectByKey ? item[selectByKey] : index;
+ const selectedItem = selectByKey ? selected : selectedIndex;
+ const key = `row_${selector}`;
+ const highlighted = selector === selectedItem;
+ const row = !renderRow ? (
+
- {rowData}
- ) :
- renderRow(rowData, rowID, highlighted);
+ {item}
+
+ ) : (
+ renderRow(item, index, highlighted)
+ );
const preservedProps = {
key,
accessible,
- onPress: () => this._onRowPress(rowData, sectionID, rowID, highlightRow),
+ onPress: () => this._onRowPress(item, index, separators),
};
- if (TOUCHABLE_ELEMENTS.find(name => name == row.type.displayName)) {
- const props = {...row.props};
+ if (TOUCHABLE_ELEMENTS.find(name => name === row.type.displayName)) {
+ const props = { ...row.props };
props.key = preservedProps.key;
props.onPress = preservedProps.onPress;
- const {children} = row.props;
+ const { children } = row.props;
switch (row.type.displayName) {
case 'TouchableHighlight': {
- return (
-
- {children}
-
- );
+ return {children};
}
case 'TouchableOpacity': {
- return (
-
- {children}
-
- );
+ return {children};
}
case 'TouchableWithoutFeedback': {
return (
@@ -362,51 +368,54 @@ export default class ModalDropdown extends Component {
break;
}
}
- return (
-
- {row}
-
- );
+ return {row};
};
-
- _onRowPress(rowData, sectionID, rowID, highlightRow) {
- const {onSelect, renderButtonText, onDropdownWillHide} = this.props;
+ _onRowPress(rowData, rowID, highlightRow) {
+ const {
+ onSelect,
+ renderButtonText,
+ onDropdownWillHide,
+ selectByKey,
+ } = this.props;
if (!onSelect || onSelect(rowID, rowData) !== false) {
- highlightRow(sectionID, rowID);
- const value = renderButtonText && renderButtonText(rowData) || rowData.toString();
+ highlightRow.highlight(rowID);
+ const value =
+ (renderButtonText && renderButtonText(rowData)) || rowData.toString();
this._nextValue = value;
this._nextIndex = rowID;
this.setState({
- buttonText: value,
- selectedIndex: rowID
+ buttonText: selectByKey ? rowData[selectByKey] : value,
+ selectedIndex: rowID,
});
}
if (!onDropdownWillHide || onDropdownWillHide() !== false) {
this.setState({
- showDropdown: false
+ showDropdown: false,
});
}
}
-
- _renderSeparator = (sectionID, rowID, adjacentRowHighlighted) => {
- const key = `spr_${rowID}`;
+ _renderSeparator = ({ leadingItem = '' }) => {
+ const key = `spr_${leadingItem}`;
+ return ;
+ };
+ render() {
return (
-
+
+ {this._renderButton()}
+ {this._renderModal()}
+
);
- };
+ }
}
-
const styles = StyleSheet.create({
button: {
- justifyContent: 'center'
+ justifyContent: 'center',
},
buttonText: {
- fontSize: 12
+ fontSize: 12,
},
modal: {
- flexGrow: 1
+ flexGrow: 1,
},
dropdown: {
position: 'absolute',
@@ -415,13 +424,13 @@ const styles = StyleSheet.create({
borderColor: 'lightgray',
borderRadius: 2,
backgroundColor: 'white',
- justifyContent: 'center'
+ justifyContent: 'center',
},
loading: {
- alignSelf: 'center'
+ alignSelf: 'center',
},
list: {
- //flexGrow: 1,
+ // flexGrow: 1,
},
rowText: {
paddingHorizontal: 6,
@@ -429,13 +438,13 @@ const styles = StyleSheet.create({
fontSize: 11,
color: 'gray',
backgroundColor: 'white',
- textAlignVertical: 'center'
+ textAlignVertical: 'center',
},
highlightedRowText: {
- color: 'black'
+ color: 'black',
},
separator: {
height: StyleSheet.hairlineWidth,
- backgroundColor: 'lightgray'
- }
+ backgroundColor: 'lightgray',
+ },
});
diff --git a/package.json b/package.json
index db7820b..d8e25a6 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-modal-dropdown",
- "version": "0.7.0",
+ "version": "0.7.1",
"description": "A react-native dropdown component for both iOS and Android.",
"keywords": [
"react",