Filter Use Case
Source code
TypeScript ts
// src/components/filter-showcase/FilterAdvanced.ts
import { defineCustomElements } from '@revolist/revogrid/loader';
import { AdvanceFilterPlugin, ColumnStretchPlugin } from '@revolist/revogrid-pro';
defineCustomElements();
import { currentTheme, useRandomData } from '../composables/useRandomData';
const { createRandomData } = useRandomData();
const { isDark } = currentTheme();
export function load(parentSelector: string) {
const grid = document.createElement('revo-grid');
grid.source = createRandomData(100);
grid.columns = [
{
name: '🆔 ID',
prop: 'id',
filter: ['number', 'slider']
},
{
name: '🍎 Fruit',
prop: 'name',
},
];
// Define plugin
grid.plugins = [AdvanceFilterPlugin, ColumnStretchPlugin];
grid.stretch = 'all';
grid.filter = {};
grid.theme = isDark() ? 'darkCompact' : 'compact';
grid.hideAttribution = true;
document.querySelector(parentSelector)?.appendChild(grid);
}
Vue vue
// src/components/filter-showcase/FilterAdvanced.vue
<template>
<div class="filter-advanced-container">
<div class="mb-4">
<label for="filterExpression" class="block text-gray-700 font-medium mb-1">
Enter Filter Expression
</label>
<div class="flex gap-2">
<textarea
id="filterExpression"
rows="2"
:class="[
'p-4 text-sm border rounded-lg shadow-sm focus:ring focus:ring-blue-200 focus:outline-none focus:border-blue-400 placeholder-gray-400 w-full transition-colors',
isDark ? 'bg-slate-800 border-slate-700 text-slate-100' : 'bg-white border-slate-200 text-slate-900'
]"
placeholder="Enter filters (e.g., fullName contains 't' and email contains '@gmail')"
v-model="filterExpression"
/>
<button
class="self-start px-4 py-2 bg-slate-800 text-white rounded-lg hover:bg-slate-700 transition-colors shadow-sm disabled:opacity-50"
@click="applyTextFilters"
>
Apply
</button>
</div>
</div>
<div class="grid-wrapper h-[500px] border border-slate-200 rounded-xl overflow-hidden shadow-sm dark:border-slate-800">
<VGrid
ref="grid"
:theme="isDark ? 'darkMaterial' : 'material'"
:columns="columns"
:source="rows"
:plugins="plugins"
:colSize="250"
stretch="all"
:filter="filter"
:hideAttribution="true"
@afterfilterapply="sync"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { currentThemeVue } from '../composables/useRandomData';
import { makeData, allColumns } from '../composables/makeData';
import {
type ColumnFilterConfig,
VGrid,
} from '@revolist/vue3-datagrid';
import {
AdvanceFilterPlugin,
ColumnStretchPlugin,
RowOddPlugin,
RowSelectPlugin,
} from '@revolist/revogrid-pro';
import { parseFilterExpression, syncFiltersToTextInput } from './parse.filters';
const { isDark } = currentThemeVue();
const grid = ref<any>(null);
const columns = ref(allColumns());
columns.value.splice(0, 1);
if (columns.value[0]) {
columns.value[0].rowSelect = true;
}
const rows = ref(makeData(1000));
const plugins = [
AdvanceFilterPlugin,
ColumnStretchPlugin,
RowOddPlugin,
RowSelectPlugin
];
const filter = ref<ColumnFilterConfig>({
multiFilterItems: {
fullName: [{ id: 0, type: 'contains', value: 't', relation: 'or' }],
email: [
{ id: 1, type: 'contains', value: '995', relation: 'or' },
{ id: 1, type: 'contains', value: 'hall', relation: 'and' },
],
},
});
// Text filter state
const filterExpression = ref('');
/**
* Sync initial state on mount if possible
*/
onMounted(() => {
// If we have items in filter ref, try to sync them to the expression text
if (filter.value.multiFilterItems) {
filterExpression.value = syncFiltersToTextInput({
detail: { multiFilterItems: filter.value.multiFilterItems }
} as any);
}
});
/**
* Parse user-entered filter expression and update the filter config.
*/
function applyTextFilters() {
const parsedFilters = parseFilterExpression(filterExpression.value);
filter.value = {
...filter.value,
multiFilterItems: parsedFilters,
};
}
function sync(e: CustomEvent) {
const newExpr = syncFiltersToTextInput(e);
// Avoid recursive updates if the text matches
if (newExpr !== filterExpression.value) {
filterExpression.value = newExpr;
}
}
</script>
React tsx
// src/components/filter-showcase/FilterAdvanced.tsx
import { useState, useMemo, useRef } from 'react';
import { RevoGrid, type DataType } from '@revolist/react-datagrid';
import {
AdvanceFilterPlugin,
ColumnStretchPlugin,
} from '@revolist/revogrid-pro';
import { useRandomData, currentTheme } from '../composables/useRandomData';
function FilterAdvanced() {
const { isDark } = currentTheme();
const { createRandomData } = useRandomData();
const gridRef = useRef<HTMLRevoGridElement>(null);
const [source] = useState<DataType[]>(createRandomData(100));
const columns = useMemo(
() => [
{
name: '🆔 ID',
prop: 'id',
filter: ['number', 'slider'],
},
{
name: '🍎 Fruit',
prop: 'name',
},
],
[]
);
const additionalData = useMemo(
() => ({
stretch: 'all',
filter: {},
}),
[]
);
return (
<RevoGrid
ref={gridRef}
columns={columns}
source={source}
additionalData={additionalData}
hide-attribution
theme={isDark() ? 'darkCompact' : 'compact'}
plugins={[AdvanceFilterPlugin, ColumnStretchPlugin]}
/>
);
}
export default FilterAdvanced; Angular ts
// src/components/filter-showcase/FilterAdvancedAngular.ts
import { Component, ViewEncapsulation } from '@angular/core';
import { RevoGrid } from '@revolist/angular-datagrid';
import { AdvanceFilterPlugin, ColumnStretchPlugin } from '@revolist/revogrid-pro';
import { currentTheme, useRandomData } from '../composables/useRandomData';
@Component({
selector: 'filter-showcase-grid',
standalone: true,
imports: [RevoGrid],
template: `
<revo-grid
[columns]="columns"
[source]="source"
stretch="all"
[filter]="filter"
[hideAttribution]="true"
[theme]="theme"
[plugins]="plugins"
style="min-height: 400px;"
></revo-grid>`,
encapsulation: ViewEncapsulation.None,
})
export class FilterShowcaseGridComponent {
theme = currentTheme().isDark() ? 'darkCompact' : 'compact';
source = useRandomData().createRandomData(100);
columns = [
{
name: '🆔 ID',
prop: 'id',
filter: ['number', 'slider'],
},
{
name: '🍎 Fruit',
prop: 'name',
},
];
filter = {};
plugins = [AdvanceFilterPlugin, ColumnStretchPlugin];
}