ag-grid-url-sync 0.5.1 → 0.5.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/README.md +244 -26
- package/dist/core/ag-grid-url-sync.d.ts +6 -0
- package/dist/core/ag-grid-url-sync.js.map +1 -1
- package/dist/core/codecs.d.ts +28 -0
- package/dist/core/codecs.js +39 -0
- package/dist/core/codecs.js.map +1 -0
- package/dist/core/data-issue-codes.d.ts +3 -0
- package/dist/core/data-issue-codes.js +10 -0
- package/dist/core/data-issue-codes.js.map +1 -0
- package/dist/core/grid-integration.d.ts +11 -1
- package/dist/core/grid-integration.js +20 -11
- package/dist/core/grid-integration.js.map +1 -1
- package/dist/core/grid-url-sync.d.ts +62 -0
- package/dist/core/grid-url-sync.js +738 -0
- package/dist/core/grid-url-sync.js.map +1 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/issues.d.ts +2 -2
- package/dist/core/issues.js +2 -9
- package/dist/core/issues.js.map +1 -1
- package/dist/core/own-write.d.ts +138 -0
- package/dist/core/own-write.js +133 -0
- package/dist/core/own-write.js.map +1 -0
- package/dist/core/types.d.ts +151 -4
- package/dist/core/types.js +4 -0
- package/dist/core/types.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.ts +3 -2
- package/dist/react/index.js +1 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/sync-holder.d.ts +22 -0
- package/dist/react/sync-holder.js +68 -0
- package/dist/react/sync-holder.js.map +1 -0
- package/dist/react/sync-options.d.ts +17 -0
- package/dist/react/sync-options.js +22 -0
- package/dist/react/sync-options.js.map +1 -0
- package/dist/react/types.d.ts +71 -3
- package/dist/react/use-ag-grid-url-sync.d.ts +3 -0
- package/dist/react/use-ag-grid-url-sync.js +310 -526
- package/dist/react/use-ag-grid-url-sync.js.map +1 -1
- package/dist/react/use-grid-url-sync.d.ts +14 -0
- package/dist/react/use-grid-url-sync.js +206 -0
- package/dist/react/use-grid-url-sync.js.map +1 -0
- package/package.json +16 -3
package/README.md
CHANGED
|
@@ -145,7 +145,7 @@ The library provides two main entry points:
|
|
|
145
145
|
|
|
146
146
|
```typescript
|
|
147
147
|
// Core functionality - works with any framework
|
|
148
|
-
import {
|
|
148
|
+
import { createGridUrlSync } from 'ag-grid-url-sync'
|
|
149
149
|
|
|
150
150
|
// React hook - for React applications
|
|
151
151
|
import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
|
|
@@ -247,7 +247,55 @@ The config form (`getFilterModel({ ...DEFAULT_CONFIG, gridApi })`) still works,
|
|
|
247
247
|
|
|
248
248
|
**💡 Pro Tip**: Use granular imports in libraries and applications where bundle size matters. All existing import patterns remain fully supported for backward compatibility.
|
|
249
249
|
|
|
250
|
-
###
|
|
250
|
+
### Vanilla JS: `createGridUrlSync`
|
|
251
|
+
|
|
252
|
+
One call gives full sync. `createGridUrlSync` applies the address bar's filters to the grid, follows the grid's filter changes, can write them to the address bar, and removes its listeners when the grid is destroyed.
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import { createGridUrlSync, individual, grouped } from 'ag-grid-url-sync'
|
|
256
|
+
|
|
257
|
+
const sync = createGridUrlSync({
|
|
258
|
+
api: gridApi,
|
|
259
|
+
codec: individual({ prefix: 'f_' }), // or grouped({ param: 'gf', format: 'json' })
|
|
260
|
+
history: 'replace', // 'none' (default) | 'replace' | 'push' | (url) => router.replace(url)
|
|
261
|
+
onIssue: ({ issue, source }) => {
|
|
262
|
+
if (issue.severity === 'warning') showToast(issue.message)
|
|
263
|
+
}
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
// The current state: { status, url, hasFilters, issues, views, activeViewId }
|
|
267
|
+
const { url, hasFilters } = sync.getSnapshot()
|
|
268
|
+
|
|
269
|
+
// Called after each change of the snapshot. Returns an unsubscribe function.
|
|
270
|
+
const unsubscribe = sync.subscribe(() => render(sync.getSnapshot()))
|
|
271
|
+
|
|
272
|
+
sync.applyUrl('https://app.com/data?f_name_contains=jo') // { issues }
|
|
273
|
+
sync.getUrl('https://app.com/share') // a share link for the grid's filters
|
|
274
|
+
sync.applyFilters({
|
|
275
|
+
name: { filterType: 'text', type: 'contains', filter: 'jo' }
|
|
276
|
+
}) // { issues }
|
|
277
|
+
sync.destroy()
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
`applyFilters` writes filters to the grid as the app's own write. When they land, the sync writes the URL in the `history` mode, as it does for a user edit. `applyUrl` writes no history, because the URL already holds those filters.
|
|
281
|
+
|
|
282
|
+
| Option | Default | Meaning |
|
|
283
|
+
| ------------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
284
|
+
| `api` | (required) | The AG Grid API |
|
|
285
|
+
| `codec` | `individual()` | How the filters are written in the URL. `individual({ prefix })` writes one param for each filter; `grouped({ param, format })` writes all filters in one param |
|
|
286
|
+
| `maxValueLength` | `200` | The longest text value that is kept |
|
|
287
|
+
| `history` | `'none'` | How a filter change goes to the address bar. `'replace'` and `'push'` use `window.history`; a function gets the URL, for a router. The page's other params, the `#hash` and `history.state` stay |
|
|
288
|
+
| `popstate` | `true` only with `'push'` | Apply the URL when the back or forward button changes it |
|
|
289
|
+
| `applyUrlOnCreate` | `true` | Apply the address bar's filters on create. A URL with no filter params keeps the grid's filters (for example from `initialState`), and with `history` they are written to the URL with replace |
|
|
290
|
+
| `views` | none | The saved views. Give `createViewStore(key)` from `ag-grid-url-sync/view-storage`. See [Saved Views](#saved-views) |
|
|
291
|
+
| `throwOnError` | `false` | Throw an issue instead of reporting it, in the methods that the app calls (`applyUrl`, `getUrl`, `applyFilters`, `saveView`, `loadView`, `deleteView`). `createGridUrlSync` and its listeners never throw |
|
|
292
|
+
| `onIssue` | none | Gets each issue one time, as `{ issue, source }`. `source` is `'url'` (the sync read the address bar), `'grid'` (it read the grid) or `'api'` (a method that the app called) |
|
|
293
|
+
|
|
294
|
+
The snapshot `status` is `'active'` from create, and `'destroyed'` after `destroy()` or after the grid is destroyed. After that, `applyUrl`, `applyFilters`, `saveView` and `loadView` report `NOT_READY` to `onIssue`. `deleteView` needs only storage, so it still works. `IDLE_SNAPSHOT` (`status: 'idle'`) is the snapshot for a time when there is no sync yet. `getSnapshot()` returns the same object until something changes, so it works with React's `useSyncExternalStore`. The sync writes no history for an `applyUrl` apply, because the URL holds those filters already. `applyFilters` and `loadView` write the URL as a user edit does. Nothing reads `window` when the module loads, and a sync made with no `window` does nothing to the address bar.
|
|
295
|
+
|
|
296
|
+
### Basic Example (deprecated `createUrlSync`)
|
|
297
|
+
|
|
298
|
+
`createUrlSync` and `AGGridUrlSync` will be removed in 0.6.0. Use `createGridUrlSync`.
|
|
251
299
|
|
|
252
300
|
```typescript
|
|
253
301
|
import { createUrlSync } from 'ag-grid-url-sync'
|
|
@@ -457,6 +505,9 @@ The library never writes to the console. Each problem goes to one callback, and
|
|
|
457
505
|
| `NOT_READY` | A hook operation called before the grid is ready | `onError` (React) |
|
|
458
506
|
| `VIEW_NOT_FOUND`, `VIEW_NAME_REQUIRED` | A saved view operation that cannot run | `onError` (React) |
|
|
459
507
|
| `STORAGE_UNAVAILABLE`, `STORAGE_FULL`, `STORAGE_WRITE_FAILED` | Browser storage for saved views failed | `onError` (React) |
|
|
508
|
+
| `HISTORY_WRITE_FAILED` | The sync could not write the address bar | `onIssue` in the core, `onError` in the React hook |
|
|
509
|
+
|
|
510
|
+
Each error has a `severity`: `'warning'` for the first seven rows, `'error'` for the others. `createGridUrlSync` sends every issue to `onIssue`; the callbacks in the table are for the deprecated API and the React hook.
|
|
460
511
|
|
|
461
512
|
The codes in the first seven rows are data issues: a filter that is dropped or is not valid. The library skips that filter and keeps the others. When the library knows the column, it is in `error.column`. `onParseError` is typed with `Error`, so check `instanceof URLSyncError` before you read `code` or `column`.
|
|
462
513
|
|
|
@@ -507,7 +558,7 @@ return issues.length > 0 ? (
|
|
|
507
558
|
|
|
508
559
|
Like TanStack Query, the library can throw an issue instead of reporting it. Set `throwOnError: true` to throw every issue, or give a function that picks issues. In the core, a thrown issue does not go to `onParseError`, and the first one stops the call. In React, the hook keeps reporting each issue to `onParseError` one time, and then throws the picked issue during render, so an error boundary catches it. The default is `false`.
|
|
509
560
|
|
|
510
|
-
|
|
561
|
+
Only `createGridUrlSync` or the hook with `history` changes the address bar. Before an error boundary resets, remove the bad param from the URL (or the filter from the grid), or the same issue is thrown again.
|
|
511
562
|
|
|
512
563
|
```tsx
|
|
513
564
|
useAGGridUrlSync(gridApi, {
|
|
@@ -533,7 +584,7 @@ Refer to the [package.json](./package.json) for the full export map.
|
|
|
533
584
|
|
|
534
585
|
## React Integration
|
|
535
586
|
|
|
536
|
-
For React applications, use the
|
|
587
|
+
For React applications, use the `useGridUrlSync` hook. It is a thin adapter on [`createGridUrlSync`](#vanilla-js-creategridurlsync): it takes the same options, and the grid behaves as with the vanilla sync. The older `useAGGridUrlSync` hook is deprecated and will be removed in 0.6.0 (see [Migrating from `useAGGridUrlSync`](#migrating-from-useaggridurlsync)).
|
|
537
588
|
|
|
538
589
|
### Installation for React
|
|
539
590
|
|
|
@@ -541,7 +592,90 @@ For React applications, use the dedicated `useAGGridUrlSync` hook that provides
|
|
|
541
592
|
npm install ag-grid-url-sync
|
|
542
593
|
```
|
|
543
594
|
|
|
544
|
-
|
|
595
|
+
The hook works with React 16.8 and later. It uses the `use-sync-external-store` package, which npm installs with the library. On React 18 and later, that package uses React's own `useSyncExternalStore`.
|
|
596
|
+
|
|
597
|
+
### `useGridUrlSync({ api, ...options })`
|
|
598
|
+
|
|
599
|
+
```tsx
|
|
600
|
+
import { useState } from 'react'
|
|
601
|
+
import { AgGridReact } from 'ag-grid-react'
|
|
602
|
+
import type { GridApi } from 'ag-grid-community'
|
|
603
|
+
import { useGridUrlSync } from 'ag-grid-url-sync/react'
|
|
604
|
+
import { individual } from 'ag-grid-url-sync'
|
|
605
|
+
|
|
606
|
+
function GridComponent() {
|
|
607
|
+
const [api, setApi] = useState<GridApi | null>(null)
|
|
608
|
+
|
|
609
|
+
const { status, hasFilters, issues, getUrl, applyFilters } = useGridUrlSync({
|
|
610
|
+
api,
|
|
611
|
+
codec: individual({ prefix: 'filter_' }),
|
|
612
|
+
history: 'push', // each filter change adds a history entry; back and forward apply the URL
|
|
613
|
+
onIssue: ({ issue, source }) => console.warn(source, issue.code)
|
|
614
|
+
})
|
|
615
|
+
|
|
616
|
+
return (
|
|
617
|
+
<div>
|
|
618
|
+
<button
|
|
619
|
+
disabled={status !== 'active'}
|
|
620
|
+
onClick={() => navigator.clipboard.writeText(getUrl())}
|
|
621
|
+
>
|
|
622
|
+
Share filters
|
|
623
|
+
</button>
|
|
624
|
+
<button disabled={!hasFilters} onClick={() => applyFilters({})}>
|
|
625
|
+
Clear filters
|
|
626
|
+
</button>
|
|
627
|
+
{issues.length > 0 && (
|
|
628
|
+
<p>The link leaves out {issues.length} filter(s)</p>
|
|
629
|
+
)}
|
|
630
|
+
<AgGridReact onGridReady={params => setApi(params.api)} {...gridProps} />
|
|
631
|
+
</div>
|
|
632
|
+
)
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
The options are the [`createGridUrlSync` options](#vanilla-js-creategridurlsync) (`codec`, `maxValueLength`, `history`, `popstate`, `applyUrlOnCreate`, `throwOnError`, `onIssue`), with these changes:
|
|
637
|
+
|
|
638
|
+
| Option | Default | Description |
|
|
639
|
+
| -------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
640
|
+
| `api` | none | The AG Grid API, or `null` while the grid starts |
|
|
641
|
+
| `storageKey` | none | Enables saved views, kept in `localStorage` under this key (in place of the core's `views` store). With no key, the view methods do nothing |
|
|
642
|
+
| `enabled` | `true` | With `false`, the hook makes no sync: `status` is `'idle'`, and a method reports `NOT_READY`. `views` still shows what is in storage. Back to `true` starts again, as a new sync does: the URL is applied again |
|
|
643
|
+
| `throwOnError` | `false` | As in TanStack Query: the hook throws a picked issue during render, so an error boundary catches it. The methods do not throw |
|
|
644
|
+
|
|
645
|
+
The hook returns the snapshot and the methods of the sync:
|
|
646
|
+
|
|
647
|
+
| Property | Description |
|
|
648
|
+
| ------------------------------------ | -------------------------------------------------------------------------------- |
|
|
649
|
+
| `status` | `'idle'` (no grid, no sync yet, or a server render), `'active'` or `'destroyed'` |
|
|
650
|
+
| `url`, `hasFilters`, `issues` | The URL with the grid's filters, whether there are filters, the latest issues |
|
|
651
|
+
| `views`, `activeViewId` | The saved views and the active one |
|
|
652
|
+
| `applyUrl(url?)`, `applyFilters(f)` | Apply a URL or filters. They return `{ issues }` |
|
|
653
|
+
| `getUrl(baseUrl?)` | The URL with the grid's filters, for example to share |
|
|
654
|
+
| `saveView`, `loadView`, `deleteView` | The saved view methods of the sync |
|
|
655
|
+
|
|
656
|
+
- **The core's rules hold.** On mount, a URL with filters wins over the stored view, a URL with no filters keeps the grid's filters, and a URL apply writes no history.
|
|
657
|
+
- **Options can change after mount.** A new codec, `maxValueLength`, history mode, `popstate` or `storageKey` makes a new sync on the same grid. It does not apply the URL again, and it keeps the active view. A new `storageKey` restores that store's view. A new codec object with the same settings, a new `onIssue` or a new `history` function makes no new sync.
|
|
658
|
+
- **The result is stable.** It is the same object until a snapshot value changes, and the methods never change.
|
|
659
|
+
- **A method with no sync** (no grid yet, `enabled: false`): `applyUrl` and `applyFilters` report `NOT_READY` to `onIssue`, and so do `saveView` and `loadView` with a `storageKey`. `getUrl` returns the base URL. `deleteView` still works with storage only.
|
|
660
|
+
- **Issues stay across a new sync.** After an option change or a `StrictMode` remount, `issues` still shows the latest apply's issues until the next apply. `onIssue` gets each issue one time.
|
|
661
|
+
- `StrictMode`, React's `<Activity>` and server rendering are supported.
|
|
662
|
+
|
|
663
|
+
### Migrating from `useAGGridUrlSync`
|
|
664
|
+
|
|
665
|
+
| `useAGGridUrlSync` | `useGridUrlSync` |
|
|
666
|
+
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
667
|
+
| `useAGGridUrlSync(gridApi, options)` | `useGridUrlSync({ api: gridApi, ...options })` |
|
|
668
|
+
| `paramPrefix`, `serialization`, `groupedParam`, `format` | `codec: individual({ prefix })` or `grouped({ param, format })` |
|
|
669
|
+
| `autoApplyOnMount` (default `false`) | `applyUrlOnCreate` (default `true`). A URL with no filters keeps the grid's filters |
|
|
670
|
+
| `enabledWhenReady` | `enabled` |
|
|
671
|
+
| `onParseError`, `onError(error, context)` | `onIssue({ issue, source })` |
|
|
672
|
+
| `isReady` | `status === 'active'` |
|
|
673
|
+
| `currentUrl`, `shareUrl(baseUrl?)` | `url`, `getUrl(baseUrl?)` |
|
|
674
|
+
| `applyUrlFilters(url?)`, `clearFilters()` | `applyUrl(url?)`, `applyFilters({})` |
|
|
675
|
+
| `getQueryParams()` | `new URL(getUrl()).search`, while `status` is `'active'` |
|
|
676
|
+
| `parseUrlFilters`, `getFiltersAsFormat`, `getSerializationMode` | The module functions `parseUrlFilters` and `serializeGrouped` from `ag-grid-url-sync` |
|
|
677
|
+
|
|
678
|
+
### Basic React Usage (deprecated `useAGGridUrlSync`)
|
|
545
679
|
|
|
546
680
|
```tsx
|
|
547
681
|
import React, { useState } from 'react'
|
|
@@ -619,7 +753,7 @@ function GridComponent() {
|
|
|
619
753
|
}
|
|
620
754
|
```
|
|
621
755
|
|
|
622
|
-
### React Hook API
|
|
756
|
+
### React Hook API (deprecated `useAGGridUrlSync`)
|
|
623
757
|
|
|
624
758
|
#### `useAGGridUrlSync(gridApi, options?)`
|
|
625
759
|
|
|
@@ -638,10 +772,35 @@ const {
|
|
|
638
772
|
parseUrlFilters,
|
|
639
773
|
applyFilters,
|
|
640
774
|
getFiltersAsFormat,
|
|
641
|
-
|
|
775
|
+
getSerializationMode
|
|
642
776
|
} = useAGGridUrlSync(gridApi, options)
|
|
643
777
|
```
|
|
644
778
|
|
|
779
|
+
The hook runs on [`createGridUrlSync`](#vanilla-js-creategridurlsync) and reads its state with `useSyncExternalStore`:
|
|
780
|
+
|
|
781
|
+
- **Options can change after mount.** A change to `paramPrefix`, `maxValueLength`, `serialization`, `groupedParam`, `format`, `history` (the mode) or `popstate` makes a new sync. The grid keeps its filters, and `currentUrl` uses the new format. The URL is not applied again. A new options object with the same values, or a new callback, makes no new sync.
|
|
782
|
+
- **The returned object is stable.** It is the same object across renders until a value in it changes.
|
|
783
|
+
- **A grid-read issue goes to `onParseError` one time** while it stays. It is reported again only after it goes away and comes back.
|
|
784
|
+
- **After AG Grid destroys the grid**, `isReady` is `false` and `currentUrl` is `''`, as with no grid. `applyUrlFilters`, `clearFilters`, `applyFilters`, `saveView` and `loadView` then report `NOT_READY` to `onError`. `shareUrl`, `getQueryParams` and `getFiltersAsFormat` return their fallback values.
|
|
785
|
+
- **The hook writes to the address bar only with `history`.** With the default `'none'`, use `currentUrl` or `shareUrl()` to update it.
|
|
786
|
+
|
|
787
|
+
#### Address bar (`history` and `popstate`)
|
|
788
|
+
|
|
789
|
+
The hook takes the `history` and `popstate` options of [`createGridUrlSync`](#vanilla-js-creategridurlsync), so a React app gets the same address-bar sync with one option:
|
|
790
|
+
|
|
791
|
+
```tsx
|
|
792
|
+
// Each filter change adds a history entry, and back and forward apply the URL
|
|
793
|
+
useAGGridUrlSync(gridApi, { autoApplyOnMount: true, history: 'push' })
|
|
794
|
+
|
|
795
|
+
// Or give the URL to a router. A new function on each render is fine.
|
|
796
|
+
useAGGridUrlSync(gridApi, { history: url => router.replace(url) })
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
- A user edit, `applyFilters`, `clearFilters` and `loadView` write the URL. `'push'` adds one entry for each of them.
|
|
800
|
+
- A URL apply writes nothing, because the URL holds those filters already: auto-apply on mount, `applyUrlFilters` and the back button.
|
|
801
|
+
- The restore of a stored view on mount replaces the entry. A new sync for an option change, or a `StrictMode` remount, adds no entry.
|
|
802
|
+
- `popstate` is `true` by default with `'push'`. On back or forward, the hook applies the new URL. The view is then no longer active, and the issues of that apply are in `issues`. A grid error goes to `onError` with the context `'popstate'`. A failed address-bar write is `HISTORY_WRITE_FAILED`, to `onError` with the context `'filter-change'`.
|
|
803
|
+
|
|
645
804
|
#### Hook Options
|
|
646
805
|
|
|
647
806
|
```tsx
|
|
@@ -652,6 +811,10 @@ interface UseAGGridUrlSyncOptions {
|
|
|
652
811
|
onParseError?: (error: Error) => void
|
|
653
812
|
throwOnError?: boolean | ((issue: URLSyncError) => boolean) // Default: false
|
|
654
813
|
|
|
814
|
+
// Address bar (see Address bar above)
|
|
815
|
+
history?: 'none' | 'replace' | 'push' | ((url: string) => void) // Default: 'none'
|
|
816
|
+
popstate?: boolean // Default: true with 'push', else false
|
|
817
|
+
|
|
655
818
|
// React-specific options
|
|
656
819
|
autoApplyOnMount?: boolean // Default: false
|
|
657
820
|
enabledWhenReady?: boolean // Default: true
|
|
@@ -664,20 +827,21 @@ interface UseAGGridUrlSyncOptions {
|
|
|
664
827
|
|
|
665
828
|
#### Hook Return Values
|
|
666
829
|
|
|
667
|
-
| Property
|
|
668
|
-
|
|
|
669
|
-
| `shareUrl`
|
|
670
|
-
| `getQueryParams`
|
|
671
|
-
| `applyUrlFilters`
|
|
672
|
-
| `clearFilters`
|
|
673
|
-
| `isReady`
|
|
674
|
-
| `currentUrl`
|
|
675
|
-
| `hasFilters`
|
|
676
|
-
| `issues`
|
|
677
|
-
| `parseUrlFilters`
|
|
678
|
-
| `applyFilters`
|
|
679
|
-
| `getFiltersAsFormat`
|
|
680
|
-
| `
|
|
830
|
+
| Property | Type | Description |
|
|
831
|
+
| ---------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
832
|
+
| `shareUrl` | `(baseUrl?: string) => string` | Generate shareable URL with current filters |
|
|
833
|
+
| `getQueryParams` | `() => string` | Get filter state as query parameters |
|
|
834
|
+
| `applyUrlFilters` | `(url?: string) => void` | Apply filters from URL to grid |
|
|
835
|
+
| `clearFilters` | `() => void` | Clear all text filters |
|
|
836
|
+
| `isReady` | `boolean` | Whether the grid API is available and the hook is ready. `false` after AG Grid destroys the grid. |
|
|
837
|
+
| `currentUrl` | `string` | Current URL with filters applied |
|
|
838
|
+
| `hasFilters` | `boolean` | Whether the grid has supported filters |
|
|
839
|
+
| `issues` | `readonly URLSyncError[]` | Filters that the latest URL apply or URL write dropped (see Error Handling) |
|
|
840
|
+
| `parseUrlFilters` | `(url: string) => FilterState` | Parse filters from URL without applying |
|
|
841
|
+
| `applyFilters` | `(filters: FilterState) => void` | Apply filter state object to grid |
|
|
842
|
+
| `getFiltersAsFormat` | `(format: 'querystring' \| 'json' \| 'base64') => string` | Serialize filters to any supported format (for sharing/export) |
|
|
843
|
+
| `getSerializationMode` | `() => 'individual' \| 'grouped'` | Get the current serialization mode (individual or grouped) |
|
|
844
|
+
| `getCurrentFormat` | `() => 'individual' \| 'grouped'` | **Deprecated** (removed in 0.6.0): use `getSerializationMode` |
|
|
681
845
|
|
|
682
846
|
Saved views (inert unless `storageKey` is set):
|
|
683
847
|
|
|
@@ -689,10 +853,58 @@ Saved views (inert unless `storageKey` is set):
|
|
|
689
853
|
| `loadView` | `(id: string \| null) => void` | Apply a saved view, or pass `null` to reset to unfiltered |
|
|
690
854
|
| `deleteView` | `(id: string) => void` | Delete a saved view |
|
|
691
855
|
|
|
692
|
-
> **Note:** `getFiltersAsFormat` and `
|
|
856
|
+
> **Note:** `getFiltersAsFormat` and `getSerializationMode` are especially useful for grouped serialization, format conversion, and advanced sharing scenarios.
|
|
693
857
|
|
|
694
858
|
### Saved Views
|
|
695
859
|
|
|
860
|
+
The views are part of `createGridUrlSync`. The React hook uses the same code, so a vanilla app and a React app get the same rules.
|
|
861
|
+
|
|
862
|
+
#### Saved views in vanilla JS
|
|
863
|
+
|
|
864
|
+
Give the `views` option a view store. `createViewStore` is in its own entry, so an app with no saved views does not get the storage code.
|
|
865
|
+
|
|
866
|
+
```ts
|
|
867
|
+
import { createGridUrlSync } from 'ag-grid-url-sync'
|
|
868
|
+
import { createViewStore } from 'ag-grid-url-sync/view-storage'
|
|
869
|
+
|
|
870
|
+
const sync = createGridUrlSync({
|
|
871
|
+
api: gridApi,
|
|
872
|
+
history: 'push',
|
|
873
|
+
views: createViewStore('orders')
|
|
874
|
+
})
|
|
875
|
+
|
|
876
|
+
const { views, activeViewId } = sync.getSnapshot()
|
|
877
|
+
|
|
878
|
+
const view = sync.saveView('Open orders') // GridView, or null if the save failed
|
|
879
|
+
sync.loadView(view.id)
|
|
880
|
+
sync.loadView(null) // clear the filters
|
|
881
|
+
sync.deleteView(view.id)
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
You can also give your own `ViewStore`, for example one that talks to a server. With no `views` option, `views` is `[]`, `activeViewId` is `null`, and the three methods do nothing.
|
|
885
|
+
|
|
886
|
+
Rules for the vanilla API:
|
|
887
|
+
|
|
888
|
+
- **`activeViewId` is tracked.** `saveView`, `loadView` and the restore of the stored view set it. A load sets it before the grid write, so a snapshot never shows `null` while the write is still pending.
|
|
889
|
+
- **Any other filter model clears it.** A user edit, `applyUrl`, `applyFilters` and a back-button apply all set `activeViewId` to `null` and clear the stored pointer. A view that AG Grid changes when it applies it stays active.
|
|
890
|
+
- **A hand edit does not make a view active.** If the user types the filters of a view, `activeViewId` stays `null`. When two views have the same model, the active one is the one the user loaded.
|
|
891
|
+
- **A view load writes the URL as a user edit does.** With `history: 'push'`, the back button goes back to the URL from before the load. If the URL does not change, the sync writes no entry. Set and multi filters are kept in a view, but the URL cannot hold them. A view that differs only in those filters adds no entry.
|
|
892
|
+
- **A URL apply writes no history.** This holds for `applyUrl`, the apply on create and the back button.
|
|
893
|
+
- **A failed grid write restores `activeViewId`.** The failure goes to `onIssue` as `GRID_ERROR`.
|
|
894
|
+
- **Deleting is conservative.** If the deleted view is active and the grid still shows it, the grid is cleared. If the user edited the filters, they stay.
|
|
895
|
+
- **Failures go to `onIssue`**, not to `snapshot.issues`. They are `NOT_READY`, `GRID_ERROR`, `VIEW_NOT_FOUND`, `VIEW_NAME_REQUIRED`, `STORAGE_FULL`, `STORAGE_UNAVAILABLE` and `STORAGE_WRITE_FAILED`. `loadView` with an unknown id reads the store again, then reports `VIEW_NOT_FOUND`. After `destroy`, `saveView` and `loadView` report `NOT_READY`, and `deleteView` still deletes from the store.
|
|
896
|
+
|
|
897
|
+
On create (when `applyUrlOnCreate` is not `false`), the sync picks the starting filters in this order:
|
|
898
|
+
|
|
899
|
+
1. The URL holds the filters of the stored view (compared in URL form). The sync restores the view with its full model, and keeps `activeViewId` and the pointer. This is how a reload keeps a view that was loaded with `history` on.
|
|
900
|
+
2. The URL has at least one filter. The URL wins. `activeViewId` is `null` and the pointer is cleared. A URL with only bad params does not win.
|
|
901
|
+
3. A stored view exists. The sync restores it. With `history` on, the URL is written with replace, so page load adds no back-button step.
|
|
902
|
+
4. Else, the grid keeps its filters.
|
|
903
|
+
|
|
904
|
+
A stored pointer that names a missing view is ignored.
|
|
905
|
+
|
|
906
|
+
#### Saved views in React
|
|
907
|
+
|
|
696
908
|
Pass a `storageKey` to let users name and revisit filter sets. The key both enables
|
|
697
909
|
the feature and namespaces its storage, so two grids on the same origin must use
|
|
698
910
|
different keys:
|
|
@@ -757,7 +969,7 @@ Behaviour worth knowing:
|
|
|
757
969
|
`onError` with context `'save-view'`. Reads degrade to an empty list instead of
|
|
758
970
|
throwing, so server rendering is safe.
|
|
759
971
|
|
|
760
|
-
|
|
972
|
+
The store is also available directly:
|
|
761
973
|
|
|
762
974
|
```ts
|
|
763
975
|
import { createViewStore } from 'ag-grid-url-sync/view-storage'
|
|
@@ -936,9 +1148,13 @@ Parameter structure:
|
|
|
936
1148
|
|
|
937
1149
|
## API Reference
|
|
938
1150
|
|
|
939
|
-
### `
|
|
1151
|
+
### `createGridUrlSync(options)`
|
|
940
1152
|
|
|
941
|
-
|
|
1153
|
+
See [Vanilla JS: `createGridUrlSync`](#vanilla-js-creategridurlsync) for the options. It returns `{ getSnapshot, subscribe, applyUrl, applyFilters, getUrl, saveView, loadView, deleteView, destroy }`. The snapshot is `{ status, url, hasFilters, issues, views, activeViewId }`. See [Saved Views](#saved-views) for the view methods.
|
|
1154
|
+
|
|
1155
|
+
### `createUrlSync(gridApi, config?)` (deprecated)
|
|
1156
|
+
|
|
1157
|
+
Factory function to create a new AGGridUrlSync instance. Deprecated: use `createGridUrlSync`. It will be removed in 0.6.0.
|
|
942
1158
|
|
|
943
1159
|
```typescript
|
|
944
1160
|
import { createUrlSync } from 'ag-grid-url-sync'
|
|
@@ -950,7 +1166,9 @@ const urlSync = createUrlSync(gridApi, {
|
|
|
950
1166
|
})
|
|
951
1167
|
```
|
|
952
1168
|
|
|
953
|
-
### `AGGridUrlSync` Class
|
|
1169
|
+
### `AGGridUrlSync` Class (deprecated)
|
|
1170
|
+
|
|
1171
|
+
Deprecated: use `createGridUrlSync`. It will be removed in 0.6.0.
|
|
954
1172
|
|
|
955
1173
|
#### Constructor
|
|
956
1174
|
|
|
@@ -2,6 +2,10 @@ import type { GridApi } from 'ag-grid-community';
|
|
|
2
2
|
import type { AGGridUrlSyncConfig, FilterState, ApplyResult, SerializationFormat, SerializationMode, UrlState } from './types.js';
|
|
3
3
|
/**
|
|
4
4
|
* AGGridUrlSync class for synchronizing AG Grid text filters with URL parameters
|
|
5
|
+
*
|
|
6
|
+
* @deprecated Use `createGridUrlSync({ api })`: it also listens to the grid
|
|
7
|
+
* and can write the address bar (#221). `AGGridUrlSync` and `createUrlSync`
|
|
8
|
+
* will be removed in 0.6.0.
|
|
5
9
|
*/
|
|
6
10
|
export declare class AGGridUrlSync {
|
|
7
11
|
private readonly gridApi;
|
|
@@ -75,5 +79,7 @@ export declare class AGGridUrlSync {
|
|
|
75
79
|
* @param gridApi - AG Grid API instance
|
|
76
80
|
* @param config - Optional configuration options
|
|
77
81
|
* @returns AGGridUrlSync instance
|
|
82
|
+
* @deprecated Use `createGridUrlSync({ api })` (#221). This function will be
|
|
83
|
+
* removed in 0.6.0.
|
|
78
84
|
*/
|
|
79
85
|
export declare function createUrlSync(gridApi: GridApi, config?: AGGridUrlSyncConfig): AGGridUrlSync;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ag-grid-url-sync.js","sourceRoot":"","sources":["../../src/core/ag-grid-url-sync.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,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;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"ag-grid-url-sync.js","sourceRoot":"","sources":["../../src/core/ag-grid-url-sync.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,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;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAS7D,MAAM,OAAO,aAAa;IACP,OAAO,CAAS;IAChB,OAAO,CAAiB;IAOzC,YAAY,OAAgB,EAAE,MAAM,GAAwB,EAAE;QAC5D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QAGtB,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAA;IACvC,CAAC;IAOD,WAAW,CAAC,OAAgB;QAC1B,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,CAAA;IACtC,CAAC;IAWD,WAAW,CAAC,OAAgB;QAC1B,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACvD,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QACzD,MAAM,GAAG,GAAG,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA;QAE3C,OAAO;YACL,GAAG,EAAE,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,OAAO,CAAC;YAC3C,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC;YAC/C,MAAM;SACP,CAAA;IACH,CAAC;IAMD,cAAc;QACZ,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QAC9B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QAE3B,OAAO,MAAM,CAAC,MAAM,CAAA;IACtB,CAAC;IAOD,YAAY,CAAC,GAAY;QACvB,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACvD,MAAM,UAAU,GAAG,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAA;QAC9C,MAAM,WAAW,GAAG,eAAe,CAAC,UAAU,EAAE,OAAO,CAAC,CAAA;QAIxD,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;QAE9C,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE,CAAA;IAC5D,CAAC;IAOD,YAAY,CAAC,WAAwB;QACnC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACvD,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAEpD,OAAO,EAAE,MAAM,EAAE,CAAA;IACnB,CAAC;IAMD,YAAY;QACV,OAAO,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;IAC9B,CAAC;IAKD,OAAO;IAEP,CAAC;IAMD,oBAAoB;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,CAAA;IACnC,CAAC;IAMD,gBAAgB;QACd,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAA;IAC5B,CAAC;IAKD,kBAAkB,CAAC,MAA2B;QAC5C,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QAG9D,MAAM,UAAU,GAAG;YACjB,GAAG,IAAI,CAAC,OAAO;YACf,MAAM;YACN,aAAa,EAAE,SAAkB;SAClC,CAAA;QAGD,MAAM,MAAM,GAAG,gBAAgB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAA;QAExD,OAAO,MAAM,CAAC,KAAK,CAAA;IACrB,CAAC;CACF;AAUD,MAAM,UAAU,aAAa,CAC3B,OAAgB,EAChB,MAA4B;IAE5B,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AAC3C,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Codec, ResolvedOptions, SerializationFormat } from './types.js';
|
|
2
|
+
/** The options that a codec sets */
|
|
3
|
+
export type CodecOptions = Pick<ResolvedOptions, 'serialization' | 'paramPrefix' | 'groupedParam' | 'format'>;
|
|
4
|
+
/**
|
|
5
|
+
* One URL param for each filter, for example `?f_name_contains=jo`
|
|
6
|
+
* @param options.prefix - The start of each param name. Default `'f_'`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function individual(options?: {
|
|
9
|
+
prefix?: string | undefined;
|
|
10
|
+
}): Codec;
|
|
11
|
+
/**
|
|
12
|
+
* All the filters in one URL param
|
|
13
|
+
* @param options.param - The param name. Default `'grid_filters'`.
|
|
14
|
+
* @param options.format - `'querystring'` (default), `'json'` or `'base64'`
|
|
15
|
+
*/
|
|
16
|
+
export declare function grouped(options?: {
|
|
17
|
+
param?: string | undefined;
|
|
18
|
+
format?: SerializationFormat | undefined;
|
|
19
|
+
}): Codec;
|
|
20
|
+
/** The options of a codec. Throws for an object that no factory made. */
|
|
21
|
+
export declare function codecOptions(codec: Codec): CodecOptions;
|
|
22
|
+
/**
|
|
23
|
+
* A codec with all four settings, for the React hook (#222). Internal: the
|
|
24
|
+
* hook's old options name the params of both modes, and the URL must strip
|
|
25
|
+
* the names that the app set, as the class does. Not exported from the
|
|
26
|
+
* package.
|
|
27
|
+
*/
|
|
28
|
+
export declare function codecFromOptions(options: CodecOptions): Codec;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { DEFAULT_CONFIG } from './options.js';
|
|
2
|
+
const settings = new WeakMap();
|
|
3
|
+
function makeCodec(options) {
|
|
4
|
+
const codec = Object.freeze({});
|
|
5
|
+
settings.set(codec, options);
|
|
6
|
+
return codec;
|
|
7
|
+
}
|
|
8
|
+
export function individual(options = {}) {
|
|
9
|
+
return makeCodec({
|
|
10
|
+
serialization: 'individual',
|
|
11
|
+
paramPrefix: options.prefix ?? DEFAULT_CONFIG.paramPrefix,
|
|
12
|
+
groupedParam: DEFAULT_CONFIG.groupedParam,
|
|
13
|
+
format: DEFAULT_CONFIG.format
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function grouped(options = {}) {
|
|
17
|
+
return makeCodec({
|
|
18
|
+
serialization: 'grouped',
|
|
19
|
+
paramPrefix: DEFAULT_CONFIG.paramPrefix,
|
|
20
|
+
groupedParam: options.param ?? DEFAULT_CONFIG.groupedParam,
|
|
21
|
+
format: options.format ?? DEFAULT_CONFIG.format
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function codecOptions(codec) {
|
|
25
|
+
const options = settings.get(codec);
|
|
26
|
+
if (!options) {
|
|
27
|
+
throw new TypeError('codec must come from individual() or grouped()');
|
|
28
|
+
}
|
|
29
|
+
return options;
|
|
30
|
+
}
|
|
31
|
+
export function codecFromOptions(options) {
|
|
32
|
+
return makeCodec({
|
|
33
|
+
serialization: options.serialization,
|
|
34
|
+
paramPrefix: options.paramPrefix,
|
|
35
|
+
groupedParam: options.groupedParam,
|
|
36
|
+
format: options.format
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=codecs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codecs.js","sourceRoot":"","sources":["../../src/core/codecs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAY7C,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAuB,CAAA;AAEnD,SAAS,SAAS,CAAC,OAAqB;IAGtC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAU,CAAA;IACxC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAE5B,OAAO,KAAK,CAAA;AACd,CAAC;AAMD,MAAM,UAAU,UAAU,CACxB,OAAO,GAAoC,EAAE;IAE7C,OAAO,SAAS,CAAC;QACf,aAAa,EAAE,YAAY;QAC3B,WAAW,EAAE,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,WAAW;QACzD,YAAY,EAAE,cAAc,CAAC,YAAY;QACzC,MAAM,EAAE,cAAc,CAAC,MAAM;KAC9B,CAAC,CAAA;AACJ,CAAC;AAOD,MAAM,UAAU,OAAO,CACrB,OAAO,GAGH,EAAE;IAEN,OAAO,SAAS,CAAC;QACf,aAAa,EAAE,SAAS;QACxB,WAAW,EAAE,cAAc,CAAC,WAAW;QACvC,YAAY,EAAE,OAAO,CAAC,KAAK,IAAI,cAAc,CAAC,YAAY;QAC1D,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,MAAM;KAChD,CAAC,CAAA;AACJ,CAAC;AAGD,MAAM,UAAU,YAAY,CAAC,KAAY;IACvC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAEnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAA;IACvE,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAQD,MAAM,UAAU,gBAAgB,CAAC,OAAqB;IACpD,OAAO,SAAS,CAAC;QACf,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-issue-codes.js","sourceRoot":"","sources":["../../src/core/data-issue-codes.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,gBAAgB,GAA2B,IAAI,GAAG,CAAY;IACzE,eAAe;IACf,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,iBAAiB;IACjB,eAAe;IACf,aAAa;CACd,CAAC,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AGGridUrlSyncConfig, FilterState, InternalConfig } from './types.js';
|
|
2
|
-
import type { GridApi } from 'ag-grid-community';
|
|
2
|
+
import type { FilterModel, GridApi } from 'ag-grid-community';
|
|
3
3
|
/**
|
|
4
4
|
* Detects the expected filter type for a column based on AG Grid configuration
|
|
5
5
|
*/
|
|
@@ -20,6 +20,11 @@ export declare function getFilterModel(gridApi: GridApi, options?: AGGridUrlSync
|
|
|
20
20
|
* `getFilterModel(gridApi, options)`. This form will be removed in 0.6.0.
|
|
21
21
|
*/
|
|
22
22
|
export declare function getFilterModel(config: InternalConfig): FilterState;
|
|
23
|
+
/**
|
|
24
|
+
* Converts an AG Grid filter model to URL filters. It does not call the grid.
|
|
25
|
+
* Filter types that the library does not support (set, multi) are skipped.
|
|
26
|
+
*/
|
|
27
|
+
export declare function fromGridModel(model: FilterModel | null | undefined, options?: AGGridUrlSyncConfig): FilterState;
|
|
23
28
|
/**
|
|
24
29
|
* Applies a filter state to AG Grid. A filter whose type does not match the
|
|
25
30
|
* column is skipped with a warning. An error from the grid is reported
|
|
@@ -38,3 +43,8 @@ export declare function applyFilterModel(filterState: FilterState, gridApi: Grid
|
|
|
38
43
|
* removed in 0.6.0.
|
|
39
44
|
*/
|
|
40
45
|
export declare function applyFilterModel(filterState: FilterState, config: InternalConfig): void;
|
|
46
|
+
/**
|
|
47
|
+
* Converts URL filters to the AG Grid filter model that `applyFilterModel`
|
|
48
|
+
* would write. It does not call `setFilterModel`.
|
|
49
|
+
*/
|
|
50
|
+
export declare function toGridModel(filterState: FilterState, gridApi: GridApi, options?: AGGridUrlSyncConfig): FilterModel;
|
|
@@ -67,6 +67,10 @@ function readGridFilters(gridApi, options) {
|
|
|
67
67
|
reportIssue(options, toIssue(error, 'GRID_ERROR'));
|
|
68
68
|
return {};
|
|
69
69
|
}
|
|
70
|
+
return fromGridModel(model, options);
|
|
71
|
+
}
|
|
72
|
+
export function fromGridModel(model, options) {
|
|
73
|
+
const resolved = resolveOptions(options);
|
|
70
74
|
const filters = new Map();
|
|
71
75
|
if (!v.is(JsonObjectSchema, model)) {
|
|
72
76
|
return {};
|
|
@@ -92,7 +96,7 @@ function readGridFilters(gridApi, options) {
|
|
|
92
96
|
if (!operator ||
|
|
93
97
|
!internalOperation ||
|
|
94
98
|
!isNumberFilterOperation(internalOperation)) {
|
|
95
|
-
reportIssue(
|
|
99
|
+
reportIssue(resolved, new InvalidFilterError(`Unknown number filter operation '${filter.type}' for column '${column}'. ` +
|
|
96
100
|
`Supported operations: ${NUMBER_FILTER_OPERATIONS.map(toAgGridOperation).join(', ')}`, undefined, { code: 'INVALID_PARAM', column }));
|
|
97
101
|
continue;
|
|
98
102
|
}
|
|
@@ -113,11 +117,11 @@ function readGridFilters(gridApi, options) {
|
|
|
113
117
|
? gridNumber(filter.filterTo, column)
|
|
114
118
|
: undefined;
|
|
115
119
|
if (numericValue instanceof InvalidFilterError) {
|
|
116
|
-
reportIssue(
|
|
120
|
+
reportIssue(resolved, numericValue);
|
|
117
121
|
continue;
|
|
118
122
|
}
|
|
119
123
|
if (numericTo instanceof InvalidFilterError) {
|
|
120
|
-
reportIssue(
|
|
124
|
+
reportIssue(resolved, numericTo);
|
|
121
125
|
continue;
|
|
122
126
|
}
|
|
123
127
|
if (isNaN(numericValue)) {
|
|
@@ -230,17 +234,27 @@ export function applyFilterModel(filterState, target, options) {
|
|
|
230
234
|
writeGridFilters(filterState, target, resolveOptions(options));
|
|
231
235
|
}
|
|
232
236
|
function writeGridFilters(filterState, gridApi, options) {
|
|
237
|
+
const model = toGridModel(filterState, gridApi, options);
|
|
238
|
+
try {
|
|
239
|
+
gridApi.setFilterModel(model);
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
reportIssue(options, toIssue(error, 'GRID_ERROR'));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
export function toGridModel(filterState, gridApi, options) {
|
|
246
|
+
const resolved = resolveOptions(options);
|
|
233
247
|
const model = new Map();
|
|
234
248
|
for (const [column, filter] of Object.entries(filterState)) {
|
|
235
249
|
if (!v.is(JsonObjectSchema, filter))
|
|
236
250
|
continue;
|
|
237
251
|
const expectedType = detectColumnFilterType(gridApi, column);
|
|
238
252
|
if (filter.filterType === 'date' && expectedType !== 'date') {
|
|
239
|
-
reportIssue(
|
|
253
|
+
reportIssue(resolved, new InvalidFilterError(`Column '${column}' expects a ${expectedType} filter but received a date filter. This may indicate a configuration mismatch in the column definition or filter application.`, undefined, { code: 'TYPE_MISMATCH', column }));
|
|
240
254
|
continue;
|
|
241
255
|
}
|
|
242
256
|
if (filter.filterType === 'number' && expectedType !== 'number') {
|
|
243
|
-
reportIssue(
|
|
257
|
+
reportIssue(resolved, new InvalidFilterError(`Column '${column}' expects a ${expectedType} filter but received a number filter. This may indicate a configuration mismatch in the column definition or filter application.`, undefined, { code: 'TYPE_MISMATCH', column }));
|
|
244
258
|
continue;
|
|
245
259
|
}
|
|
246
260
|
const agGridFilter = convertToAGGridFilter(filter);
|
|
@@ -248,11 +262,6 @@ function writeGridFilters(filterState, gridApi, options) {
|
|
|
248
262
|
model.set(column, agGridFilter);
|
|
249
263
|
}
|
|
250
264
|
}
|
|
251
|
-
|
|
252
|
-
gridApi.setFilterModel(Object.fromEntries(model));
|
|
253
|
-
}
|
|
254
|
-
catch (error) {
|
|
255
|
-
reportIssue(options, toIssue(error, 'GRID_ERROR'));
|
|
256
|
-
}
|
|
265
|
+
return Object.fromEntries(model);
|
|
257
266
|
}
|
|
258
267
|
//# sourceMappingURL=grid-integration.js.map
|