UNPKG

taro-material

Version:

Mini Program components that implement Google's Material Design.

168 lines (145 loc) 4.67 kB
import Nerv from "nervjs"; import Taro, { Component } from "@tarojs/taro-h5"; import { View, ScrollView } from '@tarojs/components'; import PropTypes from 'prop-types'; import RMTag from "../Tag/index"; import RMTypography from "../Typography/index"; import RMButton from "../Button/index"; import theme from "../styles/theme"; import './ActionFilter.scss'; const cloneDeep = o => JSON.parse(JSON.stringify(o)); class ActionFilter extends Component { constructor(props) { super(props); this.state.data = props.data; } componentWillReceiveProps(nextProps) { const { data } = this.props; if (nextProps.data !== data) { this.setState({ data: nextProps.data }); } } handleClick(i, j, immediately) { const { onChange } = this.props; const { data } = this.state; const options = cloneDeep(data); const option = options[i]; if (option.single) { option.data.forEach((item, index) => { if (index !== j) { item.active = false; } }); } const tag = option.data[j]; tag.active = !tag.active; if (option.required) { const ops = option.data.filter(item => item.active); if (ops.length <= 0) { tag.active = true; } } this.setState({ data: options }, () => { onChange(cloneDeep(options)); immediately && this.handleOkClick(); }); } handleOkClick() { const { data: options } = this.state; const { onOk } = this.props; const selections = options.map(item => { const { label, value, data } = item; const activeTag = data.filter(d => d.active); return { label, value, data: cloneDeep(activeTag) }; }).filter(item => item.data.length > 0); onOk(selections); } handleResetClick() { const { data, onReset, onChange } = this.props; const _data = cloneDeep(data); const selections = _data.map(item => { const { label, value } = item; const activeTag = item.data.filter(d => d.active); return { label, value, data: cloneDeep(activeTag) }; }).filter(item => item.data.length > 0); this.setState({ data: _data }, () => { onChange(cloneDeep(_data)); onReset(selections); }); } render() { const { data: options } = this.state; const tagCustomStyle = { borderRadius: `${theme.shape.borderRadius / 2}px`, padding: `0 ${theme.spacing.unit}px` }; const buttonCustomStyle = { width: '100%', boxShadow: 'none', borderRadius: '0px' }; return <View className="root"> <View className="action-filter"> <ScrollView scroll-y scrollX={false} style="height: calc(100vh - 48px); width: 100%;"> {options && options.map((option, i) => { const { label, value, data } = option; return <View key={value} className="option"> <View className="title"> <RMTypography className="body2">{label}</RMTypography> </View> <View className="tags"> {data.map((item, j) => <View onClick={this.handleClick.bind(this, i, j, false)} key={item.value} className="tag"> <RMTag active={false} circle={false} block color={item.active ? 'primary' : 'default'} size="normal" customStyle={tagCustomStyle}> <RMTypography color="inherit" fontSize={12} block> {item.label} </RMTypography> </RMTag> </View>)} <View className="spacing" /> </View> </View>; })} </ScrollView> </View> <View className="actions"> <View className="button"> <RMButton color="default" variant="text" onClick={this.handleResetClick} size="normal" block customStyle={buttonCustomStyle}> 重置 </RMButton> </View> <View className="button primary"> <RMButton color="primary" variant="contained" onClick={this.handleOkClick} size="normal" block customStyle={buttonCustomStyle}> 确定 </RMButton> </View> </View> </View>; } } ActionFilter.propTypes = { onOk: PropTypes.func, data: PropTypes.array, onChange: PropTypes.func, onReset: PropTypes.func }; ActionFilter.defaultProps = { onOk: () => {}, onChange: () => {}, onReset: () => {}, data: [] }; export default ActionFilter;