diff --git a/examples/docs/en-US/table.md b/examples/docs/en-US/table.md
index 0cdcfe537fc..3bae00c9fe6 100644
--- a/examples/docs/en-US/table.md
+++ b/examples/docs/en-US/table.md
@@ -1910,6 +1910,9 @@ You can customize row index in `type=index` columns.
| filters | an array of data filtering options. For each element in this array, `text` and `value` are required | Array[{ text, value }] | — | — |
| filter-placement | placement for the filter dropdown | String | same as Tooltip's `placement` | — |
| filter-multiple | whether data filtering supports multiple options | Boolean | — | true |
+| filter-search | whether the filter dropdown can search filtering options | Boolean | — | false |
+| filter-search-method | search method for filtering options. Receives `(query, filter)` and should return `true` when the option matches | Function(query, filter) | — | — |
+| filter-search-placeholder | placeholder for the filter search input | String | — | — |
| filter-method | data filtering method. If `filter-multiple` is on, this method will be called multiple times for each row, and a row will display if one of the calls returns `true` | Function(value, row, column) | — | — |
| filtered-value | filter value for selected data, might be useful when table header is rendered with `render-header` | Array | — | — |
diff --git a/packages/table/src/filter-panel.vue b/packages/table/src/filter-panel.vue
index 3220d6dc764..9a1de6d4c52 100644
--- a/packages/table/src/filter-panel.vue
+++ b/packages/table/src/filter-panel.vue
@@ -5,11 +5,19 @@
v-if="multiple"
v-clickoutside="handleOutsideClick"
v-show="showPopper">
+
+
+
+
{{ filter.text }}
@@ -27,12 +35,20 @@
v-else
v-clickoutside="handleOutsideClick"
v-show="showPopper">
+
+
+
+
- {{ t('el.table.clearFilter') }}
- this.filterSearchMethod(this.filterText, filter));
+ }
+
+ const filterText = this.filterText.toLowerCase();
+ return this.filters.filter(filter => String(filter.text).toLowerCase().indexOf(filterText) > -1);
},
filterValue: {
@@ -188,6 +232,13 @@
if (val === true && parseInt(this.popperJS._popper.style.zIndex, 10) < PopupManager.zIndex) {
this.popperJS._popper.style.zIndex = PopupManager.nextZIndex();
}
+ if (val === false) {
+ this.filterText = '';
+ }
+ },
+
+ filterText() {
+ this.$nextTick(() => this.updatePopper());
}
}
};
diff --git a/packages/table/src/table-column.js b/packages/table/src/table-column.js
index 528eff1ab11..e9ae7f981e7 100644
--- a/packages/table/src/table-column.js
+++ b/packages/table/src/table-column.js
@@ -40,6 +40,9 @@ export default {
selectable: Function,
reserveSelection: Boolean,
filterMethod: Function,
+ filterSearch: Boolean,
+ filterSearchMethod: Function,
+ filterSearchPlaceholder: String,
filteredValue: Array,
filters: Array,
filterPlacement: String,
@@ -195,7 +198,7 @@ export default {
},
registerNormalWatchers() {
- const props = ['label', 'property', 'filters', 'filterMultiple', 'sortable', 'index', 'formatter', 'className', 'labelClassName', 'showOverflowTooltip'];
+ const props = ['label', 'property', 'filters', 'filterMultiple', 'filterSearch', 'filterSearchMethod', 'filterSearchPlaceholder', 'sortable', 'index', 'formatter', 'className', 'labelClassName', 'showOverflowTooltip'];
// 一些属性具有别名
const aliases = {
prop: 'property',
@@ -270,6 +273,7 @@ export default {
filterable: this.filters || this.filterMethod,
filteredValue: [],
filterPlacement: '',
+ filterSearch: false,
isColumnGroup: false,
filterOpened: false,
// sort 相关属性
@@ -281,7 +285,7 @@ export default {
const basicProps = ['columnKey', 'label', 'className', 'labelClassName', 'type', 'renderHeader', 'formatter', 'fixed', 'resizable'];
const sortProps = ['sortMethod', 'sortBy', 'sortOrders'];
const selectProps = ['selectable', 'reserveSelection'];
- const filterProps = ['filterMethod', 'filters', 'filterMultiple', 'filterOpened', 'filteredValue', 'filterPlacement'];
+ const filterProps = ['filterMethod', 'filters', 'filterMultiple', 'filterOpened', 'filteredValue', 'filterPlacement', 'filterSearch', 'filterSearchMethod', 'filterSearchPlaceholder'];
let column = this.getPropsData(basicProps, sortProps, selectProps, filterProps);
column = mergeOptions(defaults, column);
diff --git a/packages/theme-chalk/src/table-column.scss b/packages/theme-chalk/src/table-column.scss
index 6fd54e7a47d..99ff8582c75 100644
--- a/packages/theme-chalk/src/table-column.scss
+++ b/packages/theme-chalk/src/table-column.scss
@@ -49,6 +49,11 @@
min-width: 100px;
}
+ @include e(search) {
+ min-width: 160px;
+ padding: 10px 10px 0;
+ }
+
@include e(bottom) {
border-top: 1px solid $--border-color-lighter;
padding: 8px;
@@ -94,4 +99,4 @@
margin-bottom: 0;
}
}
-}
\ No newline at end of file
+}
diff --git a/test/unit/specs/table.spec.js b/test/unit/specs/table.spec.js
index f0888d2fc2a..c6ee4d7b1d9 100644
--- a/test/unit/specs/table.spec.js
+++ b/test/unit/specs/table.spec.js
@@ -298,6 +298,8 @@ describe('Table', () => {
{ text: 'Peter Docter', value: 'Peter Docter' },
{ text: 'Andrew Stanton', value: 'Andrew Stanton' }
]"
+ :filter-search="filterSearch"
+ :filter-search-method="filterSearchMethod"
:filter-method="filterMethod"
label="导演" />
@@ -308,6 +310,13 @@ describe('Table', () => {
this.testData = getTestData();
},
+ data() {
+ return {
+ filterSearch: false,
+ filterSearchMethod: null
+ };
+ },
+
methods: {
filterMethod(value, row) {
return value === row.director;
@@ -360,6 +369,31 @@ describe('Table', () => {
}, 100);
});
+ it('filter search', done => {
+ vm.filterSearch = true;
+
+ vm.$nextTick(_ => {
+ const btn = vm.$el.querySelector('.el-table__column-filter-trigger');
+
+ triggerEvent(btn, 'click', true, false);
+ setTimeout(_ => {
+ const filter = document.body.querySelector('.el-table-filter');
+ const input = filter.querySelector('.el-table-filter__search input');
+
+ expect(input).to.exist;
+ input.value = 'Peter';
+ triggerEvent(input, 'input');
+
+ setTimeout(_ => {
+ const labels = toArray(filter.querySelectorAll('.el-checkbox__label')).map(label => label.textContent.trim());
+ expect(labels).to.eql(['Peter Docter']);
+ document.body.removeChild(filter);
+ done();
+ }, DELAY);
+ }, 100);
+ });
+ });
+
it('click reset', done => {
const btn = vm.$el.querySelector('.el-table__column-filter-trigger');
diff --git a/types/table-column.d.ts b/types/table-column.d.ts
index 34e1d3034e2..3d585630157 100644
--- a/types/table-column.d.ts
+++ b/types/table-column.d.ts
@@ -109,6 +109,15 @@ export declare class ElTableColumn extends ElementUIComponent {
/** Whether data filtering supports multiple options */
filterMultiple: Boolean
+ /** Whether the filter panel can search filtering options */
+ filterSearch: boolean
+
+ /** Search method for filtering options */
+ filterSearchMethod: (query: string, filter: TableColumnFilter) => boolean
+
+ /** Placeholder for the filter search input */
+ filterSearchPlaceholder: string
+
/** Data filtering method. If `filter-multiple` is on, this method will be called multiple times for each row, and a row will display if one of the calls returns `true` */
filterMethod: (value: any, row: object) => boolean
diff --git a/web-types.json b/web-types.json
index 5b6201b27f4..91d69d1a566 100644
--- a/web-types.json
+++ b/web-types.json
@@ -3482,6 +3482,21 @@
"description": "Whether data filtering supports multiple options",
"type": "Boolean"
},
+ {
+ "name": "filterSearch",
+ "description": "Whether the filter panel can search filtering options",
+ "type": "boolean"
+ },
+ {
+ "name": "filterSearchMethod",
+ "description": "Search method for filtering options",
+ "type": "(query: string, filter: TableColumnFilter) => boolean"
+ },
+ {
+ "name": "filterSearchPlaceholder",
+ "description": "Placeholder for the filter search input",
+ "type": "string"
+ },
{
"name": "resizable",
"description": "Whether column width can be resized. Works when border of `el-table` is `true`",