ag-grid-url-sync 0.1.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +435 -52
- package/dist/{ag-grid-url-sync.js → core/ag-grid-url-sync.js} +4 -2
- package/dist/core/ag-grid-url-sync.js.map +1 -0
- package/dist/core/grid-integration.d.ts +14 -0
- package/dist/core/grid-integration.js +156 -0
- package/dist/core/grid-integration.js.map +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +11 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/types.d.ts +107 -0
- package/dist/core/types.js +117 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/url-generator.d.ts +9 -0
- package/dist/core/url-generator.js +88 -0
- package/dist/core/url-generator.js.map +1 -0
- package/dist/core/url-parser.d.ts +9 -0
- package/dist/core/url-parser.js +164 -0
- package/dist/core/url-parser.js.map +1 -0
- package/dist/core/validation.d.ts +47 -0
- package/dist/core/validation.js +87 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/types.d.ts +64 -0
- package/dist/react/types.js +2 -0
- package/dist/react/types.js.map +1 -0
- package/dist/react/use-ag-grid-url-sync.d.ts +10 -0
- package/dist/react/use-ag-grid-url-sync.js +215 -0
- package/dist/react/use-ag-grid-url-sync.js.map +1 -0
- package/package.json +97 -8
- package/dist/ag-grid-url-sync.js.map +0 -1
- package/dist/types.d.ts +0 -69
- package/dist/types.js +0 -31
- package/dist/types.js.map +0 -1
- package/dist/utils.d.ts +0 -36
- package/dist/utils.js +0 -188
- package/dist/utils.js.map +0 -1
- /package/dist/{ag-grid-url-sync.d.ts → core/ag-grid-url-sync.d.ts} +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2025 NearForm
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
# AG Grid URL Sync
|
|
4
4
|
|
|
5
|
-
A lightweight TypeScript library for synchronizing AG Grid text filters with URL parameters, enabling shareable filter states through clean, human-readable URLs.
|
|
5
|
+
A lightweight TypeScript library for synchronizing AG Grid text and number filters with URL parameters, enabling shareable filter states through clean, human-readable URLs.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- 🔍
|
|
9
|
+
- 🔍 **Complete text filter support** - All 8 AG Grid text operations (contains, equals, not contains, not equal, starts with, ends with, blank, not blank)
|
|
10
|
+
- 🔢 **Complete number filter support** - All 9 AG Grid number operations (equals, not equal, greater than, greater than or equal, less than, less than or equal, in range, blank, not blank)
|
|
10
11
|
- 🔗 Manual URL generation for sharing filter states
|
|
11
12
|
- ↔️ Bidirectional sync between grid and URL
|
|
12
13
|
- 🛠️ Framework agnostic - works with any AG Grid setup
|
|
14
|
+
- ⚛️ **React hook** - dedicated `useAGGridUrlSync` with state management
|
|
13
15
|
- 📝 Full TypeScript support with strict mode compliance
|
|
14
16
|
- 🚦 Graceful error handling with configurable error callbacks
|
|
15
17
|
- 🧹 Clean, human-readable URL format
|
|
@@ -18,6 +20,95 @@ A lightweight TypeScript library for synchronizing AG Grid text filters with URL
|
|
|
18
20
|
- 🛡️ Robust edge case handling (special characters, malformed URLs)
|
|
19
21
|
- 📦 Lightweight bundle size (~3KB gzipped)
|
|
20
22
|
|
|
23
|
+
## Supported Filter Types
|
|
24
|
+
|
|
25
|
+
Supports **all AG Grid text and number filter operations** (17 total) with clean, human-readable URL parameters:
|
|
26
|
+
|
|
27
|
+
### Text Filters (8 operations)
|
|
28
|
+
|
|
29
|
+
| Filter Type | Operation | URL Format | Example | Description |
|
|
30
|
+
| ----------- | ------------ | ---------------------------- | -------------------------- | --------------------------- |
|
|
31
|
+
| **Text** | Contains | `f_column_contains=value` | `f_name_contains=john` | Text contains value |
|
|
32
|
+
| **Text** | Equals | `f_column_eq=value` | `f_status_eq=active` | Text equals value exactly |
|
|
33
|
+
| **Text** | Not Contains | `f_column_notContains=value` | `f_name_notContains=spam` | Text does not contain value |
|
|
34
|
+
| **Text** | Not Equal | `f_column_neq=value` | `f_status_neq=inactive` | Text does not equal value |
|
|
35
|
+
| **Text** | Starts With | `f_column_startsWith=value` | `f_email_startsWith=admin` | Text starts with value |
|
|
36
|
+
| **Text** | Ends With | `f_column_endsWith=value` | `f_file_endsWith=.pdf` | Text ends with value |
|
|
37
|
+
| **Text** | Blank | `f_column_blank=true` | `f_optional_blank=true` | Field is empty/null |
|
|
38
|
+
| **Text** | Not Blank | `f_column_notBlank=true` | `f_required_notBlank=true` | Field has any value |
|
|
39
|
+
|
|
40
|
+
### Number Filters (9 operations)
|
|
41
|
+
|
|
42
|
+
| Filter Type | Operation | URL Format | Example | Description |
|
|
43
|
+
| ----------- | --------------------- | ------------------------ | ------------------------ | ----------------------------- |
|
|
44
|
+
| **Number** | Equals | `f_column_eq=value` | `f_age_eq=30` | Number equals value exactly |
|
|
45
|
+
| **Number** | Not Equal | `f_column_neq=value` | `f_salary_neq=50000` | Number does not equal value |
|
|
46
|
+
| **Number** | Greater Than | `f_column_gt=value` | `f_experience_gt=5` | Number is greater than value |
|
|
47
|
+
| **Number** | Greater Than or Equal | `f_column_gte=value` | `f_score_gte=85` | Number is ≥ value |
|
|
48
|
+
| **Number** | Less Than | `f_column_lt=value` | `f_budget_lt=10000` | Number is less than value |
|
|
49
|
+
| **Number** | Less Than or Equal | `f_column_lte=value` | `f_hours_lte=40` | Number is ≤ value |
|
|
50
|
+
| **Number** | In Range | `f_column_range=min,max` | `f_age_range=25,45` | Number is between min and max |
|
|
51
|
+
| **Number** | Blank | `f_column_blank=true` | `f_bonus_blank=true` | Field is empty/null |
|
|
52
|
+
| **Number** | Not Blank | `f_column_notBlank=true` | `f_salary_notBlank=true` | Field has any numeric value |
|
|
53
|
+
|
|
54
|
+
> **💡 Naming Convention Note**: URL parameters use short, clean names for better readability (`eq` for equals, `neq` for not equal). These are automatically converted to the proper AG Grid operation names (`equals`, `notEqual`) internally. This design keeps URLs concise while maintaining full compatibility with AG Grid's filter API.
|
|
55
|
+
|
|
56
|
+
### Filter Detection
|
|
57
|
+
|
|
58
|
+
The library automatically works with:
|
|
59
|
+
|
|
60
|
+
- **Text columns** configured with `filter: 'agTextColumnFilter'`
|
|
61
|
+
- **Number columns** configured with `filter: 'agNumberColumnFilter'`
|
|
62
|
+
- **Auto-detection** based on `cellDataType: 'number'` configuration
|
|
63
|
+
- Columns with `filter: true` (AG Grid's default text filter)
|
|
64
|
+
- Any column where users apply text or number-based filters
|
|
65
|
+
- All AG Grid text and number filter operations through the filter menu
|
|
66
|
+
- **Mixed filter types** - combine text and number filters in the same URL
|
|
67
|
+
|
|
68
|
+
### URL Examples
|
|
69
|
+
|
|
70
|
+
**Simple text filter:**
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
https://app.com/data?f_name_contains=john
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Simple number filter:**
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
https://app.com/data?f_salary_gt=75000
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Mixed text and number filters:**
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
https://app.com/data?f_name_contains=john&f_department_eq=Engineering&f_salary_gte=80000&f_age_range=25,45
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Complex filtering with range operations:**
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
https://app.com/data?f_name_contains=manager&f_salary_range=60000,100000&f_experience_gte=5&f_status_eq=active
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**All text operations:**
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
https://app.com/data?f_name_contains=john&f_email_startsWith=admin&f_status_neq=inactive&f_description_endsWith=test&f_optional_blank=true&f_required_notBlank=true&f_tags_notContains=spam&f_title_eq=manager
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**All number operations:**
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
https://app.com/data?f_age_eq=30&f_salary_neq=50000&f_experience_gt=5&f_score_gte=85&f_budget_lt=10000&f_hours_lte=40&f_age_range=25,45&f_bonus_blank=true&f_salary_notBlank=true
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Blank operations (both text and number):**
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
https://app.com/data?f_comments_blank=true&f_bonus_blank=true&f_name_notBlank=true&f_salary_notBlank=true
|
|
110
|
+
```
|
|
111
|
+
|
|
21
112
|
## Installation
|
|
22
113
|
|
|
23
114
|
```bash
|
|
@@ -26,6 +117,96 @@ npm install ag-grid-url-sync
|
|
|
26
117
|
|
|
27
118
|
## Usage
|
|
28
119
|
|
|
120
|
+
### Importing the Library
|
|
121
|
+
|
|
122
|
+
The library provides two main entry points:
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// Core functionality - works with any framework
|
|
126
|
+
import { createUrlSync } from 'ag-grid-url-sync'
|
|
127
|
+
|
|
128
|
+
// React hook - for React applications
|
|
129
|
+
import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
|
|
130
|
+
|
|
131
|
+
// TypeScript types (available from both imports)
|
|
132
|
+
import type { FilterState, AGGridUrlSyncConfig } from 'ag-grid-url-sync'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Tree-Shaking & Granular Imports
|
|
136
|
+
|
|
137
|
+
For optimal bundle sizes, you can import only the specific utilities you need:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import {
|
|
141
|
+
validateFilterValue,
|
|
142
|
+
DEFAULT_CONFIG
|
|
143
|
+
} from 'ag-grid-url-sync/validation'
|
|
144
|
+
|
|
145
|
+
import { parseUrlFilters, parseFilterParam } from 'ag-grid-url-sync/url-parser'
|
|
146
|
+
|
|
147
|
+
import { serializeFilters, generateUrl } from 'ag-grid-url-sync/url-generator'
|
|
148
|
+
|
|
149
|
+
import {
|
|
150
|
+
getFilterModel,
|
|
151
|
+
applyFilterModel
|
|
152
|
+
} from 'ag-grid-url-sync/grid-integration'
|
|
153
|
+
|
|
154
|
+
import type {
|
|
155
|
+
FilterState,
|
|
156
|
+
ColumnFilter,
|
|
157
|
+
FilterOperation
|
|
158
|
+
} from 'ag-grid-url-sync/types'
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Bundle Size Comparison
|
|
162
|
+
|
|
163
|
+
| Import Pattern | Bundle Size | Use Case |
|
|
164
|
+
| ---------------- | ----------- | ---------------------- |
|
|
165
|
+
| Full library | 5KB | Complete functionality |
|
|
166
|
+
| Core class only | 3.2KB | Basic URL sync |
|
|
167
|
+
| React hook only | 7KB | React applications |
|
|
168
|
+
| URL parsing only | 1.05KB | Parse existing URLs |
|
|
169
|
+
| Validation only | 318B | Input validation |
|
|
170
|
+
| Types only | 0B | TypeScript types |
|
|
171
|
+
|
|
172
|
+
#### Example: Custom URL Parser
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
import { parseUrlFilters } from 'ag-grid-url-sync/url-parser'
|
|
176
|
+
import { DEFAULT_CONFIG } from 'ag-grid-url-sync/validation'
|
|
177
|
+
import type { FilterState } from 'ag-grid-url-sync/types'
|
|
178
|
+
|
|
179
|
+
function getFiltersFromUrl(url: string): FilterState {
|
|
180
|
+
const config = {
|
|
181
|
+
gridApi: null, // Not needed for parsing
|
|
182
|
+
...DEFAULT_CONFIG,
|
|
183
|
+
onParseError: error => console.error('Parse error:', error)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return parseUrlFilters(url, config)
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
#### Example: Custom URL Generator
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
import { generateUrl, serializeFilters } from 'ag-grid-url-sync/url-generator'
|
|
194
|
+
import type { FilterState } from 'ag-grid-url-sync/types'
|
|
195
|
+
|
|
196
|
+
function createShareableUrl(filters: FilterState, baseUrl: string): string {
|
|
197
|
+
const config = {
|
|
198
|
+
gridApi: null, // Not needed for generation
|
|
199
|
+
paramPrefix: 'f_',
|
|
200
|
+
maxValueLength: 200,
|
|
201
|
+
onParseError: () => {}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return generateUrl(baseUrl, filters, config)
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**💡 Pro Tip**: Use granular imports in libraries and applications where bundle size matters. All existing import patterns remain fully supported for backward compatibility.
|
|
209
|
+
|
|
29
210
|
### Basic Example
|
|
30
211
|
|
|
31
212
|
```typescript
|
|
@@ -34,50 +215,240 @@ import { createUrlSync } from 'ag-grid-url-sync'
|
|
|
34
215
|
// Initialize with AG Grid API
|
|
35
216
|
const urlSync = createUrlSync(gridApi)
|
|
36
217
|
|
|
37
|
-
// Generate shareable URL with current filters
|
|
218
|
+
// Generate shareable URL with current filters (text and number)
|
|
38
219
|
const shareableUrl = urlSync.generateUrl()
|
|
220
|
+
// Result: https://app.com/data?f_name_contains=john&f_salary_gte=80000&f_age_range=25,45
|
|
39
221
|
|
|
40
|
-
// Apply filters from URL
|
|
41
|
-
urlSync.applyFromUrl(
|
|
222
|
+
// Apply filters from URL (automatically detects text vs number columns)
|
|
223
|
+
urlSync.applyFromUrl(
|
|
224
|
+
'https://app.com/data?f_name_contains=manager&f_salary_gt=75000'
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
// Apply specific filter programmatically
|
|
228
|
+
urlSync.applyFilters({
|
|
229
|
+
name: { filterType: 'text', type: 'contains', filter: 'john' },
|
|
230
|
+
salary: { filterType: 'number', type: 'greaterThan', filter: 75000 },
|
|
231
|
+
age: { filterType: 'number', type: 'inRange', filter: 25, filterTo: 45 }
|
|
232
|
+
})
|
|
42
233
|
|
|
43
|
-
// Clear all text filters
|
|
234
|
+
// Clear all text and number filters
|
|
44
235
|
urlSync.clearFilters()
|
|
45
236
|
```
|
|
46
237
|
|
|
47
|
-
|
|
238
|
+
## React Integration
|
|
239
|
+
|
|
240
|
+
For React applications, use the dedicated `useAGGridUrlSync` hook that provides a complete solution with React-specific features and state management.
|
|
241
|
+
|
|
242
|
+
### Installation for React
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
npm install ag-grid-url-sync
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Basic React Usage
|
|
48
249
|
|
|
49
250
|
```tsx
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
251
|
+
import React, { useState } from 'react'
|
|
252
|
+
import { AgGridReact } from 'ag-grid-react'
|
|
253
|
+
import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
|
|
254
|
+
|
|
255
|
+
function GridComponent() {
|
|
256
|
+
const [gridApi, setGridApi] = useState(null)
|
|
257
|
+
|
|
258
|
+
const {
|
|
259
|
+
shareUrl,
|
|
260
|
+
applyUrlFilters,
|
|
261
|
+
clearFilters,
|
|
262
|
+
hasFilters,
|
|
263
|
+
isReady,
|
|
264
|
+
currentUrl
|
|
265
|
+
} = useAGGridUrlSync(gridApi, {
|
|
266
|
+
autoApplyOnMount: true,
|
|
267
|
+
paramPrefix: 'filter_'
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
const handleShare = async () => {
|
|
271
|
+
const url = shareUrl()
|
|
272
|
+
await navigator.clipboard.writeText(url)
|
|
273
|
+
alert('Filter URL copied!')
|
|
274
|
+
}
|
|
52
275
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
276
|
+
return (
|
|
277
|
+
<div>
|
|
278
|
+
<div style={{ marginBottom: '10px' }}>
|
|
279
|
+
<button onClick={handleShare} disabled={!isReady}>
|
|
280
|
+
📋 Share Filters
|
|
281
|
+
</button>
|
|
282
|
+
<button onClick={clearFilters} disabled={!hasFilters}>
|
|
283
|
+
🗑️ Clear Filters
|
|
284
|
+
</button>
|
|
285
|
+
<button onClick={applyUrlFilters}>🔄 Apply URL Filters</button>
|
|
286
|
+
</div>
|
|
287
|
+
|
|
288
|
+
<div className="ag-theme-alpine" style={{ height: 400, width: '100%' }}>
|
|
289
|
+
<AgGridReact
|
|
290
|
+
onGridReady={params => setGridApi(params.api)}
|
|
291
|
+
rowData={rowData}
|
|
292
|
+
columnDefs={[
|
|
293
|
+
{
|
|
294
|
+
field: 'name',
|
|
295
|
+
filter: 'agTextColumnFilter',
|
|
296
|
+
floatingFilter: true
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
field: 'email',
|
|
300
|
+
filter: 'agTextColumnFilter',
|
|
301
|
+
floatingFilter: true
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
field: 'salary',
|
|
305
|
+
filter: 'agNumberColumnFilter',
|
|
306
|
+
floatingFilter: true
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
field: 'age',
|
|
310
|
+
filter: 'agNumberColumnFilter',
|
|
311
|
+
floatingFilter: true
|
|
312
|
+
}
|
|
313
|
+
]}
|
|
314
|
+
defaultColDef={{
|
|
315
|
+
flex: 1,
|
|
316
|
+
sortable: true,
|
|
317
|
+
resizable: true
|
|
318
|
+
}}
|
|
319
|
+
/>
|
|
320
|
+
</div>
|
|
321
|
+
</div>
|
|
57
322
|
)
|
|
323
|
+
}
|
|
324
|
+
```
|
|
58
325
|
|
|
59
|
-
|
|
326
|
+
### React Hook API
|
|
60
327
|
|
|
61
|
-
|
|
328
|
+
#### `useAGGridUrlSync(gridApi, options?)`
|
|
62
329
|
|
|
63
|
-
|
|
330
|
+
```tsx
|
|
331
|
+
import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
|
|
332
|
+
|
|
333
|
+
const {
|
|
334
|
+
shareUrl,
|
|
335
|
+
getQueryParams,
|
|
336
|
+
applyUrlFilters,
|
|
337
|
+
clearFilters,
|
|
338
|
+
isReady,
|
|
339
|
+
currentUrl,
|
|
340
|
+
hasFilters,
|
|
341
|
+
parseUrlFilters,
|
|
342
|
+
applyFilters
|
|
343
|
+
} = useAGGridUrlSync(gridApi, options)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
#### Hook Options
|
|
347
|
+
|
|
348
|
+
```tsx
|
|
349
|
+
interface UseAGGridUrlSyncOptions {
|
|
350
|
+
// Core options (same as createUrlSync)
|
|
351
|
+
paramPrefix?: string // Default: 'f_'
|
|
352
|
+
maxValueLength?: number // Default: 200
|
|
353
|
+
onParseError?: (error: Error) => void
|
|
354
|
+
|
|
355
|
+
// React-specific options
|
|
356
|
+
autoApplyOnMount?: boolean // Default: false
|
|
357
|
+
enabledWhenReady?: boolean // Default: true
|
|
64
358
|
}
|
|
359
|
+
```
|
|
65
360
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
361
|
+
#### Hook Return Values
|
|
362
|
+
|
|
363
|
+
| Property | Type | Description |
|
|
364
|
+
| ----------------- | -------------------------------- | ----------------------------------------------- |
|
|
365
|
+
| `shareUrl` | `(baseUrl?: string) => string` | Generate shareable URL with current filters |
|
|
366
|
+
| `getQueryParams` | `() => string` | Get filter state as query parameters |
|
|
367
|
+
| `applyUrlFilters` | `(url?: string) => void` | Apply filters from URL to grid |
|
|
368
|
+
| `clearFilters` | `() => void` | Clear all text filters |
|
|
369
|
+
| `isReady` | `boolean` | Whether grid API is available and hook is ready |
|
|
370
|
+
| `currentUrl` | `string` | Current URL with filters applied |
|
|
371
|
+
| `hasFilters` | `boolean` | Whether grid has any active text filters |
|
|
372
|
+
| `parseUrlFilters` | `(url: string) => FilterState` | Parse filters from URL without applying |
|
|
373
|
+
| `applyFilters` | `(filters: FilterState) => void` | Apply filter state object to grid |
|
|
374
|
+
|
|
375
|
+
### React Features
|
|
376
|
+
|
|
377
|
+
- **🔄 Automatic State Management**: Tracks grid state and filter changes automatically
|
|
378
|
+
- **⚡ Ready State**: `isReady` indicates when the grid API is available
|
|
379
|
+
- **🎯 Auto-Apply**: `autoApplyOnMount` applies URL filters when component mounts
|
|
380
|
+
- **🧹 Cleanup**: Automatically cleans up resources when component unmounts
|
|
381
|
+
- **🛡️ Error Boundaries**: Graceful error handling with configurable callbacks
|
|
382
|
+
- **📊 Filter Status**: `hasFilters` tracks whether any filters are active
|
|
383
|
+
|
|
384
|
+
### Advanced React Example
|
|
385
|
+
|
|
386
|
+
```tsx
|
|
387
|
+
import React, { useState, useEffect } from 'react'
|
|
388
|
+
import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
|
|
389
|
+
|
|
390
|
+
function AdvancedGridComponent() {
|
|
391
|
+
const [gridApi, setGridApi] = useState(null)
|
|
392
|
+
const [shareMessage, setShareMessage] = useState('')
|
|
393
|
+
|
|
394
|
+
const {
|
|
395
|
+
shareUrl,
|
|
396
|
+
applyUrlFilters,
|
|
397
|
+
clearFilters,
|
|
398
|
+
hasFilters,
|
|
399
|
+
isReady,
|
|
400
|
+
currentUrl,
|
|
401
|
+
parseUrlFilters
|
|
402
|
+
} = useAGGridUrlSync(gridApi, {
|
|
403
|
+
autoApplyOnMount: true,
|
|
404
|
+
paramPrefix: 'emp_',
|
|
405
|
+
maxValueLength: 100,
|
|
406
|
+
onParseError: error => {
|
|
407
|
+
console.warn('Filter parsing error:', error.message)
|
|
408
|
+
setShareMessage('Invalid filter URL detected')
|
|
409
|
+
}
|
|
410
|
+
})
|
|
411
|
+
|
|
412
|
+
// Watch for URL changes
|
|
413
|
+
useEffect(() => {
|
|
414
|
+
if (currentUrl !== window.location.href) {
|
|
415
|
+
setShareMessage('Filters have changed - URL ready to share')
|
|
416
|
+
}
|
|
417
|
+
}, [currentUrl])
|
|
418
|
+
|
|
419
|
+
const handleShareToEmail = () => {
|
|
420
|
+
const url = shareUrl()
|
|
421
|
+
const subject = 'Check out this filtered data'
|
|
422
|
+
const body = `View the filtered data here: ${url}`
|
|
423
|
+
window.open(
|
|
424
|
+
`mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`
|
|
425
|
+
)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const handlePreviewFilters = () => {
|
|
429
|
+
const url = prompt('Enter URL to preview filters:')
|
|
430
|
+
if (url) {
|
|
431
|
+
const filters = parseUrlFilters(url)
|
|
432
|
+
console.log('Parsed filters:', filters)
|
|
433
|
+
alert(`Found ${Object.keys(filters).length} filter(s)`)
|
|
434
|
+
}
|
|
435
|
+
}
|
|
69
436
|
|
|
70
437
|
return (
|
|
71
438
|
<div>
|
|
72
|
-
<
|
|
73
|
-
onClick={
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
439
|
+
<div className="controls">
|
|
440
|
+
<button onClick={handleShareToEmail} disabled={!isReady}>
|
|
441
|
+
📧 Share via Email
|
|
442
|
+
</button>
|
|
443
|
+
<button onClick={handlePreviewFilters}>👁️ Preview URL Filters</button>
|
|
444
|
+
<button onClick={clearFilters} disabled={!hasFilters}>
|
|
445
|
+
Clear ({hasFilters ? 'has filters' : 'no filters'})
|
|
446
|
+
</button>
|
|
447
|
+
</div>
|
|
448
|
+
|
|
449
|
+
{shareMessage && <div className="message">{shareMessage}</div>}
|
|
450
|
+
|
|
451
|
+
{/* Grid component */}
|
|
81
452
|
</div>
|
|
82
453
|
)
|
|
83
454
|
}
|
|
@@ -89,16 +460,20 @@ The library generates clean, human-readable URLs:
|
|
|
89
460
|
|
|
90
461
|
```
|
|
91
462
|
Base URL: https://app.com/page
|
|
92
|
-
With filters: https://app.com/page?f_name_contains=john&f_status_eq=active
|
|
463
|
+
With text filters: https://app.com/page?f_name_contains=john&f_status_eq=active
|
|
464
|
+
With number filters: https://app.com/page?f_salary_gte=75000&f_age_range=25,45
|
|
465
|
+
Mixed filters: https://app.com/page?f_name_contains=john&f_salary_gte=75000&f_age_lt=50
|
|
93
466
|
```
|
|
94
467
|
|
|
95
468
|
Parameter structure:
|
|
96
469
|
|
|
97
470
|
- Prefix: `f_` (configurable - useful for multi-grid scenarios)
|
|
98
471
|
- Format: `f_{columnName}_{operation}={value}`
|
|
99
|
-
- Operations
|
|
472
|
+
- **Text Operations**: `contains`, `eq`, `neq`, `startsWith`, `endsWith`, `notContains`, `blank`, `notBlank`
|
|
473
|
+
- **Number Operations**: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `range`, `blank`, `notBlank`
|
|
474
|
+
- **Range Format**: `f_column_range=min,max` (comma-separated values)
|
|
100
475
|
- Standard URL encoding for special characters
|
|
101
|
-
- Supports column names with underscores (e.g., `user_id`, `created_date`)
|
|
476
|
+
- Supports column names with underscores (e.g., `user_id`, `salary_base`, `created_date`)
|
|
102
477
|
|
|
103
478
|
## API Reference
|
|
104
479
|
|
|
@@ -203,35 +578,43 @@ interface AGGridUrlSyncConfig {
|
|
|
203
578
|
|
|
204
579
|
Check out the [examples](./examples) directory for comprehensive working demos:
|
|
205
580
|
|
|
206
|
-
###
|
|
581
|
+
### 🚀 [Vanilla JavaScript Demo](./examples/vanilla-js/demo.html)
|
|
207
582
|
|
|
208
|
-
|
|
583
|
+
Comprehensive demonstration showcasing all features:
|
|
209
584
|
|
|
210
|
-
-
|
|
211
|
-
-
|
|
212
|
-
-
|
|
213
|
-
-
|
|
585
|
+
- **Complete text filter support** - All 8 AG Grid text operations (contains, equals, not contains, not equal, starts with, ends with, blank, not blank)
|
|
586
|
+
- **Complete number filter support** - All 9 AG Grid number operations (equals, not equal, greater than, greater than or equal, less than, less than or equal, in range, blank, not blank)
|
|
587
|
+
- **Mixed filter scenarios** - Text and number filters working together (Sales team + salary filters, Engineering + experience, Executive view with high salaries)
|
|
588
|
+
- **Number operation demos** - Dedicated buttons for salary ranges, age filtering, experience thresholds, and blank number fields
|
|
589
|
+
- **URL sharing workflow** - Copy to clipboard, email, and Slack integration
|
|
590
|
+
- **Performance monitoring** - Real-time benchmarks and stress testing with mixed filter types
|
|
591
|
+
- **Error handling** - Malformed URL and invalid filter testing for both text and numbers
|
|
592
|
+
- **Complete API showcase** - Generate URLs, apply filters, clear filters with comprehensive examples
|
|
214
593
|
|
|
215
|
-
###
|
|
594
|
+
### ⚛️ [React Integration](./examples/react-basic/basic-grid.tsx)
|
|
216
595
|
|
|
217
|
-
|
|
596
|
+
Clean React component showing the `useAGGridUrlSync` hook:
|
|
218
597
|
|
|
219
|
-
-
|
|
220
|
-
-
|
|
221
|
-
-
|
|
222
|
-
-
|
|
223
|
-
-
|
|
598
|
+
- React hook integration with AG Grid for text and number filters
|
|
599
|
+
- Automatic filter state management for mixed filter types
|
|
600
|
+
- Share button with clipboard functionality
|
|
601
|
+
- Filter status indicators and controls
|
|
602
|
+
- Auto-apply filters on component mount with both text and number support
|
|
603
|
+
- Enhanced employee data with salary, age, and experience columns
|
|
604
|
+
- Full TypeScript support with comprehensive type coverage
|
|
224
605
|
|
|
225
|
-
###
|
|
606
|
+
### 📊 [Shared Data](./examples/shared-data.js)
|
|
226
607
|
|
|
227
|
-
|
|
608
|
+
Common data and column definitions used across examples:
|
|
228
609
|
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
232
|
-
-
|
|
610
|
+
- Enhanced employee data with salary, age, and experience number fields
|
|
611
|
+
- Project data with budget and numeric fields for comprehensive testing
|
|
612
|
+
- Column definitions with complete text and number filter support
|
|
613
|
+
- All 8 text filter operations and 9 number filter operations enabled
|
|
614
|
+
- Realistic data ranges for demonstrating number filters (salaries $58K-$95K, ages 26-42, experience 3-15 years)
|
|
615
|
+
- Includes null values for demonstrating blank/notBlank operations
|
|
233
616
|
|
|
234
|
-
All examples work out-of-the-box
|
|
617
|
+
All examples work out-of-the-box and demonstrate the complete functionality. The HTML demo can be opened directly in your browser, while the React example shows clean integration patterns.
|
|
235
618
|
|
|
236
619
|
## Contributing
|
|
237
620
|
|
|
@@ -243,6 +626,6 @@ All examples work out-of-the-box by opening the HTML files in your browser.
|
|
|
243
626
|
|
|
244
627
|
## License
|
|
245
628
|
|
|
246
|
-
This project is licensed under the
|
|
629
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
247
630
|
|
|
248
631
|
[](https://www.nearform.com/contact/?utm_source=open-source&utm_medium=banner&utm_campaign=os-project-pages)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { DEFAULT_CONFIG } from './
|
|
2
|
-
import { parseUrlFilters
|
|
1
|
+
import { DEFAULT_CONFIG } from './validation.js';
|
|
2
|
+
import { parseUrlFilters } from './url-parser.js';
|
|
3
|
+
import { generateUrl } from './url-generator.js';
|
|
4
|
+
import { getFilterModel, applyFilterModel } from './grid-integration.js';
|
|
3
5
|
/**
|
|
4
6
|
* AGGridUrlSync class for synchronizing AG Grid text filters with URL parameters
|
|
5
7
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ag-grid-url-sync.js","sourceRoot":"","sources":["../../src/core/ag-grid-url-sync.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAExE;;GAEG;AACH,MAAM,OAAO,aAAa;IAChB,MAAM,CAAgB;IAE9B;;;;OAIG;IACH,YAAY,OAAgB,EAAE,SAA8B,EAAE;QAC5D,IAAI,CAAC,MAAM,GAAG;YACZ,OAAO;YACP,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,cAAc,CAAC,WAAW;YAC7D,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,cAAc,CAAC,cAAc;YACtE,YAAY,EAAE,MAAM,CAAC,YAAY,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;SAChD,CAAA;IACH,CAAC;IAED;;;;OAIG;IACH,WAAW,CAAC,OAAgB;QAC1B,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC/C,MAAM,GAAG,GAAG,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA;QAC3C,OAAO,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACnD,CAAC;IAED;;;OAGG;IACH,cAAc;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QAC9B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAC3B,OAAO,MAAM,CAAC,MAAM,CAAA;IACtB,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,GAAY;QACvB,MAAM,UAAU,GAAG,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA;QAC9C,MAAM,WAAW,GAAG,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QAC5D,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;IAChC,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,WAAwB;QACnC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAC5C,CAAC;IAED;;OAEG;IACH,YAAY;QACV,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;IACvB,CAAC;IAED;;OAEG;IACH,OAAO;QACL,2DAA2D;IAC7D,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAgB,EAChB,MAA4B;IAE5B,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AAC3C,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FilterState, InternalConfig } from './types.js';
|
|
2
|
+
import type { GridApi } from 'ag-grid-community';
|
|
3
|
+
/**
|
|
4
|
+
* Detects the expected filter type for a column based on AG Grid configuration
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectColumnFilterType(gridApi: GridApi, columnId: string): 'text' | 'number' | null;
|
|
7
|
+
/**
|
|
8
|
+
* Gets the current filter model from AG Grid
|
|
9
|
+
*/
|
|
10
|
+
export declare function getFilterModel(config: InternalConfig): FilterState;
|
|
11
|
+
/**
|
|
12
|
+
* Applies a filter state to AG Grid
|
|
13
|
+
*/
|
|
14
|
+
export declare function applyFilterModel(filterState: FilterState, config: InternalConfig): void;
|