@uiw/react-native
Version:
UIW for React Native
203 lines (184 loc) • 5.65 kB
JavaScript
import { View, Text, StyleSheet, TouchableHighlight } from 'react-native';
import React, { Component } from 'react';
import { Picker } from '@react-native-picker/picker';
import arrayTreeFilter from '../utils/arrayTreeFilter';
import Modal from '../Modal';
import { colors } from '../utils';
export default class SelectCascader extends Component {
static defaultProps = {
dismissText: '取消',
okText: '确定',
title: '请选择',
cols: 3,
maskClosable: true
};
state = {
value: new Array(),
modalVisible: this.props.visible,
controlVisible: 'props'
};
static getDerivedStateFromProps(props, state) {
if (JSON.stringify(props.value) === JSON.stringify(state.value) && state.controlVisible === 'props' && state.modalVisible === props.visible) {
return null;
}
if (JSON.stringify(props.value) === JSON.stringify(state.value)) {
return {
modalVisible: state.controlVisible === 'props' ? props.visible : state.modalVisible,
controlVisible: 'props'
};
}
const getValue = (d, val) => {
let data = d || props.data;
let value = val || props.value || props.defaultValue;
if (!value || !value.length || value.indexOf(undefined) > -1) {
value = [];
for (let i = 0; i < props.cols; i++) {
if (data && data.length) {
value[i] = data[0].value;
if (data[0].children) {
data = data[0].children;
}
}
}
}
return value;
};
if (JSON.stringify(props.value) !== JSON.stringify(state.value) && state.controlVisible === 'props' && state.modalVisible === props.visible) {
return {
value: getValue(props.data, props.value)
};
}
return {
value: getValue(props.data, props.value),
modalVisible: state.controlVisible === 'props' ? props.visible : state.modalVisible,
controlVisible: 'props'
};
}
getSel(value) {
if (!value) {
return '';
}
const treeChildren = arrayTreeFilter(this.props.data, (c, level) => {
return c.value === value[level];
});
return treeChildren.map(v => {
return v.label;
}).join(',');
}
onValueChange = (itemValue, index) => {
const value = this.state.value.concat();
value[index] = itemValue;
const children = arrayTreeFilter(this.props.data, (c, level) => {
return level <= index && c.value === value[level];
});
let data = children[index];
let i;
for (i = index + 1; data && data.children && data.children.length && i < this.props.cols; i++) {
data = data.children[0];
value[i] = data.value;
}
value.length = i;
value[index] = itemValue;
this.setState({
value
});
if (this.props.onChange) {
this.props.onChange(value, this.getSel(value));
}
};
getCols = () => {
const {
data,
cols,
pickerItemStyle
} = this.props;
const {
value
} = this.state;
const childrenTree = arrayTreeFilter(data, (c, level) => {
return c.value === value[level];
}).map(c => c.children);
const needPad = cols - childrenTree.length;
if (needPad > 0) {
for (let i = 0; i < needPad; i++) {
childrenTree.push([]);
}
}
childrenTree.length = cols - 1;
childrenTree.unshift(data);
return childrenTree.map((children = [], level) => <Picker key={level} // eslint-disable-next-line react-native/no-inline-styles
style={{
flex: 1
}} selectedValue={value[level]} onValueChange={itemValue => this.onValueChange(itemValue, level)} itemStyle={pickerItemStyle}>
{children.map(item => <Picker.Item value={item.value} label={item.label} key={item.value} />)}
</Picker>);
};
onDismiss = () => {
if (this.props.onDismiss) {
this.props.onDismiss();
}
};
onOk = () => {
if (this.props.onOk) {
const {
value
} = this.state;
this.props.onOk(value, this.getSel(value));
}
};
render() {
const {
title,
dismissText,
okText,
activeOpacity = 1,
underlayColor = '#f1f1f1',
onDismiss,
headerStyle,
maskClosable,
renderDismissNode,
renderTitleNode,
renderOkNode
} = this.props;
const cols = this.getCols();
return <Modal visible={this.state.modalVisible} onClosed={() => {
maskClosable && this.setState({
modalVisible: false,
controlVisible: 'state'
});
}}>
<>
<View style={[styles.header, headerStyle]}>
<TouchableHighlight activeOpacity={activeOpacity} underlayColor={underlayColor} onPress={onDismiss} style={[styles.headerItem]}>
{renderDismissNode ?? <Text>{dismissText}</Text>}
</TouchableHighlight>
<View style={[styles.headerItem]}>{renderTitleNode ?? <Text>{title}</Text>}</View>
<TouchableHighlight activeOpacity={activeOpacity} underlayColor={underlayColor} onPress={this.onOk} style={[styles.headerItem]}>
{renderOkNode ?? <Text>{okText}</Text>}
</TouchableHighlight>
</View>
<View style={styles.list}>{cols}</View>
</>
</Modal>;
}
}
const styles = StyleSheet.create({
header: {
height: 44,
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'center',
borderBottomWidth: 1,
borderBottomColor: colors.blue
},
headerItem: {
height: 44,
alignItems: 'center',
justifyContent: 'center',
flex: 1
},
list: {
flexDirection: 'row',
alignItems: 'center'
}
});