Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add multiselect filter #587

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions dev/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,30 @@ export default {
],
},
},
{
label: 'Multiselect',
field: 'multiselect',
filterOptions: {
enabled: true,
filterMultiselectDropdownItems: [
{ id: 1, label: 'hello'},
'oh no'
],
},
},
{
label: 'Average age',
field: 'average',
type: 'number',
filterOptions: {
enabled: true,
filterMultiselectDropdownItems: [
1,
1.5,
2
],
},
},
],
rows: [
// { id:1, name:"John", age: 20, createdAt: '2018-02-18T00:00:43-05:00',score: 0.03343 },
Expand All @@ -146,6 +170,8 @@ export default {
score: 0.03343,
bool: true,
exact: 'match',
multiselect: 'hello',
average: 1
},
{
id: 3,
Expand All @@ -155,6 +181,8 @@ export default {
score: 0.03343,
bool: true,
exact: 'match',
multiselect: 'oh no',
average: null
},
{
id: 4,
Expand All @@ -164,6 +192,7 @@ export default {
score: 0.03343,
bool: false,
exact: null,
multiselect: null
},
{
id: 5,
Expand All @@ -173,6 +202,8 @@ export default {
score: 0.03343,
bool: null,
exact: 'rematch',
multiselect: 'hello world',
average: 2
},
{
id: 5,
Expand All @@ -182,6 +213,8 @@ export default {
score: 0.03343,
bool: null,
exact: 'rematch',
multiselect: 'hello',
average: 3
},
{
id: 5,
Expand All @@ -191,6 +224,8 @@ export default {
score: 0.03343,
bool: null,
exact: null,
multiselect: 'hello',
average: 2
},
{
id: 6,
Expand All @@ -200,6 +235,8 @@ export default {
score: 0.03343,
bool: true,
exact: 'match',
multiselect: 'hello',
average: 1.5
},
{
id: 7,
Expand All @@ -209,6 +246,8 @@ export default {
score: null,
bool: 'false',
exact: null,
multiselect: 'hello',
average: 1
},
{
id: 8,
Expand All @@ -218,6 +257,8 @@ export default {
score: 0.03343,
bool: true,
exact: 'rematch',
multiselect: 'hello',
average: 1
},
],
};
Expand Down
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
"lodash.clonedeep": "^4.5.0",
"lodash.filter": "^4.6.0",
"lodash.foreach": "^4.5.0",
"lodash.isequal": "^4.5.0"
"lodash.isequal": "^4.5.0",
"vue-select": "^3.1.0"
},
"devDependencies": {
"@vuepress/plugin-google-analytics": "^1.0.0-rc.1",
Expand Down
33 changes: 33 additions & 0 deletions src/components/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,33 @@ export default {
return classes;
},

filterMultiselectItems(column, row) {
const columnFieldName = column.field;
const columnFilters = this.columnFilters[columnFieldName];
if (column.filterOptions && column.filterOptions.filterMultiselectDropdownItems) {
if (columnFilters.length === 0) {
return true;
}

// Otherwise Use default filters
const typeDef = column.typeDef;
for (let filter of columnFilters) {
let filterLabel = filter;
if (typeof filter === 'object') {
filterLabel = filter.label;
}
if (typeDef.filterPredicate(
this.collect(row, columnFieldName),
filterLabel
)) {
return true;
}
}
return false;
}
return undefined;
},

// method to filter rows
filterRows(columnFilters, fromFilter = true) {
// if (!this.rows.length) return;
Expand Down Expand Up @@ -1228,6 +1255,12 @@ export default {
this.columnFilters[col.field]
);
}

const filterMultiselect = this.filterMultiselectItems(col, row);
if (filterMultiselect !== undefined) {
return filterMultiselect;
}

// Otherwise Use default filters
const { typeDef } = col;
return typeDef.filterPredicate(
Expand Down
26 changes: 25 additions & 1 deletion src/components/VgtFilterRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<div
v-if="isFilterable(column)">
<input v-if="!isDropdown(column)"
<input v-if="!isDropdown(column) && !isMultiselectDropdown(column)"
type="text"
class="vgt-input"
:placeholder="getPlaceholder(column)"
Expand Down Expand Up @@ -41,6 +41,16 @@
:key="i"
:value="option.value">{{ option.text }}</option>
</select>

<v-select v-if="isMultiselectDropdown(column)"
:options="column.filterOptions.filterMultiselectDropdownItems"
:loading="column.filterOptions.loading"
:placeholder="getPlaceholder(column)"
multiple
@input="(selectedItems) => updateFiltersOnKeyup(column, selectedItems)"
ref="vgt-multiselect"
/>

</div>
</th>
</tr>
Expand Down Expand Up @@ -93,6 +103,12 @@ export default {
methods: {
reset(emitEvent = false) {
this.columnFilters = {};

// Clear the selection in the multiselect
this.$refs['vgt-multiselect'].forEach((ref) => {
ref.clearSelection();
});

if (emitEvent) {
this.$emit('filter-changed', this.columnFilters);
}
Expand All @@ -119,6 +135,14 @@ export default {
&& typeof column.filterOptions.filterDropdownItems[0] !== 'object';
},

isMultiselectDropdown(column) {
return (
this.isFilterable(column) &&
column.filterOptions &&
column.filterOptions.filterMultiselectDropdownItems
);
},

// get column's defined placeholder or default one
getPlaceholder(column) {
const placeholder = (this.isFilterable(column) && column.filterOptions.placeholder) || `Filter ${column.label}`;
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import VueGoodTable from './components/Table.vue';
import vSelect from 'vue-select';

const VueGoodTablePlugin = {
install(Vue, options) {
Vue.component('v-select', vSelect);
Vue.component(VueGoodTable.name, VueGoodTable);
},
};
Expand Down
21 changes: 20 additions & 1 deletion src/styles/_input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,23 @@
outline: none;
border-color: $link-color;
}
}
}

.v-select {
border-radius: 4px;
color: $text-color;
&::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
color: $text-color;
opacity: 0.3; /* Firefox */
}
&:focus {
outline: none;
border-color: $link-color;
}
input {
color: $text-color
}
.vs__open-indicator {
fill: $text-color
}
}
10 changes: 10 additions & 0 deletions src/styles/black-rhino/black-rhino.scss
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@
opacity: 0.3; /* Firefox */
}
}

.v-select {
background-color: $input-bg;
input {
color: $text-color;
}
.vs__open-indicator {
fill: $text-color
}
}
}

.vgt-wrap.black-rhino{
Expand Down
10 changes: 10 additions & 0 deletions src/styles/nocturnal/nocturnal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@
opacity: 0.3; /* Firefox */
}
}

.v-select {
background-color: darken($thead-bg-color-2, 5%);
input {
color: $text-color;
}
.vs__open-indicator {
fill: $text-color
}
}
}

.vgt-wrap.nocturnal{
Expand Down
3 changes: 3 additions & 0 deletions src/styles/style.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// V-select plugin
@import "../../node_modules/vue-select/dist/vue-select";

// base table styles
@import './variables';
@import './utils';
Expand Down
20 changes: 20 additions & 0 deletions vp-docs/guide/configuration/column-filter-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ columns: [
placeholder: 'Filter This Thing', // placeholder for filter input
filterValue: 'Jane', // initial populated value for this filter
filterDropdownItems: [], // dropdown (with selected values) instead of text input
filterMultiselectDropdownItems: [], // dropdown (with multiple selected values) instead of text input
filterFn: this.columnFilterFn, //custom filter function that
trigger: 'enter', //only trigger on enter not on keyup
},
Expand Down Expand Up @@ -61,6 +62,25 @@ filterDropdownItems: [
],
```

## filterMultiselectDropdownItems

type `Array of strings` or `Array of objects` with labels

allows creating a dropdown for filtering multiple items as opposed to an input

```javascript
//array of strings
filterMultiselectDropdownItems: ['Blue', 'Red', 'Yellow']
```
```javascript
//array of objects
filterMultiselectDropdownItems: [
{ id: 1, label: 'Blue' },
{ id: 2, label: 'Red' },
{ id: 3, label: 'Yellow' }
]
```

## filterFn

type `Function`
Expand Down