UNPKG

ant-design-vue

Version:

An enterprise-class UI design language and Vue-based implementation

383 lines (344 loc) 12.5 kB
import _defineProperty from 'babel-runtime/helpers/defineProperty'; import _extends from 'babel-runtime/helpers/extends'; import Menu, { SubMenu, Item as MenuItem } from '../vc-menu'; import closest from 'dom-closest'; import classNames from 'classnames'; import shallowequal from 'shallowequal'; import Dropdown from '../dropdown'; import Icon from '../icon'; import Checkbox from '../checkbox'; import Radio from '../radio'; import FilterDropdownMenuWrapper from './FilterDropdownMenuWrapper'; import { FilterMenuProps } from './interface'; import { initDefaultProps, getOptionProps, isValidElement } from '../_util/props-util'; import { cloneElement } from '../_util/vnode'; import BaseMixin from '../_util/BaseMixin'; import { generateValueMaps } from './util'; function stopPropagation(e) { e.stopPropagation(); } export default { name: 'FilterMenu', mixins: [BaseMixin], props: initDefaultProps(FilterMenuProps, { handleFilter: function handleFilter() {}, column: {} }), data: function data() { var visible = 'filterDropdownVisible' in this.column ? this.column.filterDropdownVisible : false; this.preProps = _extends({}, getOptionProps(this)); return { sSelectedKeys: this.selectedKeys, sKeyPathOfSelectedItem: {}, // 记录所有有选中子菜单的祖先菜单 sVisible: visible, sValueKeys: generateValueMaps(this.column.filters) }; }, watch: { _propsSymbol: function _propsSymbol() { var nextProps = getOptionProps(this); var column = nextProps.column; var newState = {}; /** * if the state is visible the component should ignore updates on selectedKeys prop to avoid * that the user selection is lost * this happens frequently when a table is connected on some sort of realtime data * Fixes https://github.com/ant-design/ant-design/issues/10289 and * https://github.com/ant-design/ant-design/issues/10209 */ if ('selectedKeys' in nextProps && !shallowequal(this.preProps.selectedKeys, nextProps.selectedKeys)) { newState.sSelectedKeys = nextProps.selectedKeys; } if (!shallowequal((this.preProps.column || {}).filters, (nextProps.column || {}).filters)) { newState.sValueKeys = generateValueMaps(nextProps.column.filters); } if ('filterDropdownVisible' in column) { newState.sVisible = column.filterDropdownVisible; } if (Object.keys(newState).length > 0) { this.setState(newState); } this.preProps = _extends({}, nextProps); } }, mounted: function mounted() { var _this = this; var column = this.column; this.$nextTick(function () { _this.setNeverShown(column); }); }, updated: function updated() { var _this2 = this; var column = this.column; this.$nextTick(function () { _this2.setNeverShown(column); }); }, methods: { getDropdownVisible: function getDropdownVisible() { return this.neverShown ? false : this.sVisible; }, setNeverShown: function setNeverShown(column) { var rootNode = this.$el; var filterBelongToScrollBody = !!closest(rootNode, '.ant-table-scroll'); if (filterBelongToScrollBody) { // When fixed column have filters, there will be two dropdown menus // Filter dropdown menu inside scroll body should never be shown // To fix https://github.com/ant-design/ant-design/issues/5010 and // https://github.com/ant-design/ant-design/issues/7909 this.neverShown = !!column.fixed; } }, setSelectedKeys: function setSelectedKeys(_ref) { var selectedKeys = _ref.selectedKeys; this.setState({ sSelectedKeys: selectedKeys }); }, setVisible: function setVisible(visible) { var column = this.column; if (!('filterDropdownVisible' in column)) { this.setState({ sVisible: visible }); } if (column.onFilterDropdownVisibleChange) { column.onFilterDropdownVisibleChange(visible); } }, handleClearFilters: function handleClearFilters() { this.setState({ sSelectedKeys: [] }, this.handleConfirm); }, handleConfirm: function handleConfirm() { var _this3 = this; this.setVisible(false); this.confirmFilter2(); // Call `setSelectedKeys` & `confirm` in the same time will make filter data not up to date // https://github.com/ant-design/ant-design/issues/12284 this.$forceUpdate(); this.$nextTick(function () { _this3.confirmFilter; }); }, onVisibleChange: function onVisibleChange(visible) { this.setVisible(visible); var column = this.$props.column; // https://github.com/ant-design/ant-design/issues/17833 if (!visible && !(column.filterDropdown instanceof Function)) { this.confirmFilter2(); } }, handleMenuItemClick: function handleMenuItemClick(info) { var selectedKeys = this.$data.sSelectedKeys; if (!info.keyPath || info.keyPath.length <= 1) { return; } var keyPathOfSelectedItem = this.$data.sKeyPathOfSelectedItem; if (selectedKeys && selectedKeys.indexOf(info.key) >= 0) { // deselect SubMenu child delete keyPathOfSelectedItem[info.key]; } else { // select SubMenu child keyPathOfSelectedItem[info.key] = info.keyPath; } this.setState({ sKeyPathOfSelectedItem: keyPathOfSelectedItem }); }, hasSubMenu: function hasSubMenu() { var _column$filters = this.column.filters, filters = _column$filters === undefined ? [] : _column$filters; return filters.some(function (item) { return !!(item.children && item.children.length > 0); }); }, confirmFilter2: function confirmFilter2() { var _$props = this.$props, column = _$props.column, propSelectedKeys = _$props.selectedKeys, confirmFilter = _$props.confirmFilter; var _$data = this.$data, selectedKeys = _$data.sSelectedKeys, valueKeys = _$data.sValueKeys; var filterDropdown = column.filterDropdown; if (!shallowequal(selectedKeys, propSelectedKeys)) { confirmFilter(column, filterDropdown ? selectedKeys : selectedKeys.map(function (key) { return valueKeys[key]; }).filter(function (key) { return key !== undefined; })); } }, renderMenus: function renderMenus(items) { var _this4 = this; var h = this.$createElement; var _$props2 = this.$props, dropdownPrefixCls = _$props2.dropdownPrefixCls, prefixCls = _$props2.prefixCls; return items.map(function (item) { if (item.children && item.children.length > 0) { var sKeyPathOfSelectedItem = _this4.sKeyPathOfSelectedItem; var containSelected = Object.keys(sKeyPathOfSelectedItem).some(function (key) { return sKeyPathOfSelectedItem[key].indexOf(item.value) >= 0; }); var subMenuCls = classNames(prefixCls + '-dropdown-submenu', _defineProperty({}, dropdownPrefixCls + '-submenu-contain-selected', containSelected)); return h( SubMenu, { attrs: { title: item.text, popupClassName: subMenuCls }, key: item.value }, [_this4.renderMenus(item.children)] ); } return _this4.renderMenuItem(item); }); }, renderFilterIcon: function renderFilterIcon() { var _classNames2; var h = this.$createElement; var column = this.column, locale = this.locale, prefixCls = this.prefixCls, selectedKeys = this.selectedKeys; var filtered = selectedKeys && selectedKeys.length > 0; var filterIcon = column.filterIcon; if (typeof filterIcon === 'function') { filterIcon = filterIcon(filtered, column); } var dropdownIconClass = classNames((_classNames2 = {}, _defineProperty(_classNames2, prefixCls + '-selected', 'filtered' in column ? column.filtered : filtered), _defineProperty(_classNames2, prefixCls + '-open', this.getDropdownVisible()), _classNames2)); if (!filterIcon) { return h(Icon, { attrs: { title: locale.filterTitle, type: 'filter', theme: 'filled' }, 'class': dropdownIconClass, on: { 'click': stopPropagation } }); } if (filterIcon.length === 1 && isValidElement(filterIcon[0])) { return cloneElement(filterIcon[0], { on: { click: stopPropagation }, 'class': classNames(prefixCls + '-icon', dropdownIconClass) }); } return h( 'span', { 'class': classNames(prefixCls + '-icon', dropdownIconClass) }, [filterIcon] ); }, renderMenuItem: function renderMenuItem(item) { var h = this.$createElement; var column = this.column; var selectedKeys = this.$data.sSelectedKeys; var multiple = 'filterMultiple' in column ? column.filterMultiple : true; var input = multiple ? h(Checkbox, { attrs: { checked: selectedKeys && selectedKeys.indexOf(item.value) >= 0 } }) : h(Radio, { attrs: { checked: selectedKeys && selectedKeys.indexOf(item.value) >= 0 } }); return h( MenuItem, { key: item.value }, [input, h('span', [item.text])] ); } }, render: function render() { var _this5 = this; var h = arguments[0]; var originSelectedKeys = this.$data.sSelectedKeys; var column = this.column, locale = this.locale, prefixCls = this.prefixCls, dropdownPrefixCls = this.dropdownPrefixCls, getPopupContainer = this.getPopupContainer; // default multiple selection in filter dropdown var multiple = 'filterMultiple' in column ? column.filterMultiple : true; var dropdownMenuClass = classNames(_defineProperty({}, dropdownPrefixCls + '-menu-without-submenu', !this.hasSubMenu())); var filterDropdown = column.filterDropdown; if (filterDropdown instanceof Function) { filterDropdown = filterDropdown({ prefixCls: dropdownPrefixCls + '-custom', setSelectedKeys: function setSelectedKeys(selectedKeys) { return _this5.setSelectedKeys({ selectedKeys: selectedKeys }); }, selectedKeys: originSelectedKeys, confirm: this.handleConfirm, clearFilters: this.handleClearFilters, filters: column.filters, visible: this.getDropdownVisible(), column: column }); } var menus = filterDropdown ? h( FilterDropdownMenuWrapper, { 'class': prefixCls + '-dropdown' }, [filterDropdown] ) : h( FilterDropdownMenuWrapper, { 'class': prefixCls + '-dropdown' }, [h( Menu, { attrs: { multiple: multiple, prefixCls: dropdownPrefixCls + '-menu', selectedKeys: originSelectedKeys && originSelectedKeys.map(function (val) { return val; }), getPopupContainer: getPopupContainer }, on: { 'click': this.handleMenuItemClick, 'select': this.setSelectedKeys, 'deselect': this.setSelectedKeys }, 'class': dropdownMenuClass }, [this.renderMenus(column.filters)] ), h( 'div', { 'class': prefixCls + '-dropdown-btns' }, [h( 'a', { 'class': prefixCls + '-dropdown-link confirm', on: { 'click': this.handleConfirm } }, [locale.filterConfirm] ), h( 'a', { 'class': prefixCls + '-dropdown-link clear', on: { 'click': this.handleClearFilters } }, [locale.filterReset] )] )] ); return h( Dropdown, { attrs: { trigger: ['click'], placement: 'bottomRight', visible: this.getDropdownVisible(), getPopupContainer: getPopupContainer, forceRender: true }, on: { 'visibleChange': this.onVisibleChange } }, [h( 'template', { slot: 'overlay' }, [menus] ), this.renderFilterIcon()] ); } };