@memberjunction/ng-query-grid 4.0.0 → 4.2.0
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 +59 -313
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
# @memberjunction/ng-query-grid
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Deprecated**: Use [`@memberjunction/ng-query-viewer`](../query-viewer/README.md) instead. This component will be removed in a future version. The replacement provides state persistence, parameter persistence, entity linking, and auto-run capability.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The Query Grid component is designed to seamlessly display results from MemberJunction queries in a highly configurable Kendo UI Grid. It handles all the complexity of data loading, pagination, and user interactions while providing a clean API for developers to integrate query results into their Angular applications.
|
|
8
|
-
|
|
9
|
-
## Features
|
|
10
|
-
|
|
11
|
-
- **Query-Based Data Display**: Execute and display results from any MemberJunction query
|
|
12
|
-
- **Virtual Scrolling**: Efficient handling of large datasets with virtual scrolling
|
|
13
|
-
- **Pagination**: Built-in pagination with configurable page size (default: 40 rows)
|
|
14
|
-
- **Excel Export**: One-click export to Excel with automatic filename generation
|
|
15
|
-
- **Sorting and Reordering**: Sort columns and reorder them via drag and drop
|
|
16
|
-
- **Column Resizing**: Resize columns to fit your data
|
|
17
|
-
- **Row Selection**: Select rows for further operations
|
|
18
|
-
- **Row Click Events**: Handle row clicks with detailed event data
|
|
19
|
-
- **Loading States**: Visual feedback during data fetching
|
|
20
|
-
- **Responsive Layout**: Automatically fills container with `mjFillContainer` directive
|
|
21
|
-
- **Refresh Capability**: Built-in refresh button to reload data
|
|
22
|
-
- **Deferred Loading**: Control when data loads with the `AllowLoad` input
|
|
5
|
+
An Angular component for running and displaying stored query results in a Kendo UI grid.
|
|
23
6
|
|
|
24
7
|
## Installation
|
|
25
8
|
|
|
@@ -27,342 +10,105 @@ The Query Grid component is designed to seamlessly display results from MemberJu
|
|
|
27
10
|
npm install @memberjunction/ng-query-grid
|
|
28
11
|
```
|
|
29
12
|
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
The Query Grid component runs a stored query via `RunQuery` and renders results in a Kendo virtual-scrolling grid. It supports Excel export and provides click events for navigating to entity records from query results.
|
|
16
|
+
|
|
17
|
+
```mermaid
|
|
18
|
+
flowchart LR
|
|
19
|
+
A["RunQueryParams"] --> B["QueryGridComponent"]
|
|
20
|
+
B --> C["RunQuery API"]
|
|
21
|
+
C --> D["Kendo Grid (Virtual Scroll)"]
|
|
22
|
+
D --> E["Row Clicked Event"]
|
|
23
|
+
D --> F["Excel Export"]
|
|
24
|
+
|
|
25
|
+
style A fill:#2d6a9f,stroke:#1a4971,color:#fff
|
|
26
|
+
style B fill:#7c5295,stroke:#563a6b,color:#fff
|
|
27
|
+
style D fill:#2d8659,stroke:#1a5c3a,color:#fff
|
|
28
|
+
style F fill:#b8762f,stroke:#8a5722,color:#fff
|
|
29
|
+
```
|
|
30
|
+
|
|
30
31
|
## Usage
|
|
31
32
|
|
|
32
|
-
### Import
|
|
33
|
+
### Module Import
|
|
33
34
|
|
|
34
35
|
```typescript
|
|
35
36
|
import { QueryGridModule } from '@memberjunction/ng-query-grid';
|
|
36
37
|
|
|
37
38
|
@NgModule({
|
|
38
|
-
imports: [
|
|
39
|
-
QueryGridModule,
|
|
40
|
-
// other imports
|
|
41
|
-
],
|
|
42
|
-
// ...
|
|
39
|
+
imports: [QueryGridModule]
|
|
43
40
|
})
|
|
44
|
-
export class YourModule {
|
|
41
|
+
export class YourModule {}
|
|
45
42
|
```
|
|
46
43
|
|
|
47
|
-
### Basic
|
|
44
|
+
### Basic Usage
|
|
48
45
|
|
|
49
46
|
```html
|
|
50
|
-
<!-- Basic query grid with default settings -->
|
|
51
47
|
<mj-query-grid
|
|
52
48
|
[Params]="queryParams"
|
|
49
|
+
[BottomMargin]="50"
|
|
53
50
|
(rowClicked)="onRowClicked($event)">
|
|
54
51
|
</mj-query-grid>
|
|
55
52
|
```
|
|
56
53
|
|
|
57
|
-
### Advanced Configuration
|
|
58
|
-
|
|
59
|
-
```html
|
|
60
|
-
<!-- Fully configured query grid -->
|
|
61
|
-
<mj-query-grid
|
|
62
|
-
[Params]="queryParams"
|
|
63
|
-
[BottomMargin]="20"
|
|
64
|
-
[AutoNavigate]="false"
|
|
65
|
-
[AllowLoad]="isReadyToLoad"
|
|
66
|
-
[InEditMode]="false"
|
|
67
|
-
[EditMode]="'None'"
|
|
68
|
-
(rowClicked)="handleRowClick($event)">
|
|
69
|
-
</mj-query-grid>
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### Complete TypeScript Example
|
|
73
|
-
|
|
74
54
|
```typescript
|
|
75
|
-
import { Component, OnInit, ViewChild } from '@angular/core';
|
|
76
55
|
import { RunQueryParams } from '@memberjunction/core';
|
|
77
|
-
import { GridRowClickedEvent, QueryGridComponent } from '@memberjunction/ng-query-grid';
|
|
78
56
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<div class="orders-container">
|
|
83
|
-
<h2>Customer Orders</h2>
|
|
84
|
-
|
|
85
|
-
<div class="controls">
|
|
86
|
-
<button kendoButton (click)="refreshData()">
|
|
87
|
-
<span class="fa-solid fa-refresh"></span> Refresh
|
|
88
|
-
</button>
|
|
89
|
-
|
|
90
|
-
<label>
|
|
91
|
-
Date Range:
|
|
92
|
-
<input type="date" [(ngModel)]="startDate" (change)="updateQueryParams()">
|
|
93
|
-
to
|
|
94
|
-
<input type="date" [(ngModel)]="endDate" (change)="updateQueryParams()">
|
|
95
|
-
</label>
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
<div class="grid-container" style="height: 600px;">
|
|
99
|
-
<mj-query-grid
|
|
100
|
-
#orderGrid
|
|
101
|
-
[Params]="orderQueryParams"
|
|
102
|
-
[AutoNavigate]="false"
|
|
103
|
-
[AllowLoad]="true"
|
|
104
|
-
(rowClicked)="onOrderRowClicked($event)">
|
|
105
|
-
</mj-query-grid>
|
|
106
|
-
</div>
|
|
107
|
-
|
|
108
|
-
<div *ngIf="selectedOrder" class="order-details">
|
|
109
|
-
<h3>Selected Order Details</h3>
|
|
110
|
-
<dl>
|
|
111
|
-
<dt>Order ID:</dt>
|
|
112
|
-
<dd>{{ getOrderField('OrderID') }}</dd>
|
|
113
|
-
|
|
114
|
-
<dt>Customer:</dt>
|
|
115
|
-
<dd>{{ getOrderField('CustomerName') }}</dd>
|
|
116
|
-
|
|
117
|
-
<dt>Order Date:</dt>
|
|
118
|
-
<dd>{{ getOrderField('OrderDate') | date }}</dd>
|
|
119
|
-
|
|
120
|
-
<dt>Total Amount:</dt>
|
|
121
|
-
<dd>{{ getOrderAmount() | currency }}</dd>
|
|
122
|
-
</dl>
|
|
123
|
-
</div>
|
|
124
|
-
</div>
|
|
125
|
-
`,
|
|
126
|
-
styles: [`
|
|
127
|
-
.orders-container {
|
|
128
|
-
padding: 20px;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.controls {
|
|
132
|
-
margin-bottom: 20px;
|
|
133
|
-
display: flex;
|
|
134
|
-
gap: 20px;
|
|
135
|
-
align-items: center;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
.grid-container {
|
|
139
|
-
border: 1px solid #ddd;
|
|
140
|
-
margin-bottom: 20px;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
.order-details {
|
|
144
|
-
background: #f5f5f5;
|
|
145
|
-
padding: 20px;
|
|
146
|
-
border-radius: 4px;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
dl {
|
|
150
|
-
display: grid;
|
|
151
|
-
grid-template-columns: 150px 1fr;
|
|
152
|
-
gap: 10px;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
dt {
|
|
156
|
-
font-weight: bold;
|
|
157
|
-
}
|
|
158
|
-
`]
|
|
159
|
-
})
|
|
160
|
-
export class CustomerOrdersComponent implements OnInit {
|
|
161
|
-
@ViewChild('orderGrid') orderGrid!: QueryGridComponent;
|
|
162
|
-
|
|
163
|
-
orderQueryParams: RunQueryParams;
|
|
164
|
-
selectedOrder: GridRowClickedEvent | null = null;
|
|
165
|
-
startDate: string;
|
|
166
|
-
endDate: string;
|
|
167
|
-
|
|
168
|
-
constructor() {
|
|
169
|
-
// Initialize dates
|
|
170
|
-
const today = new Date();
|
|
171
|
-
const lastMonth = new Date(today.getFullYear(), today.getMonth() - 1, today.getDate());
|
|
172
|
-
|
|
173
|
-
this.startDate = lastMonth.toISOString().split('T')[0];
|
|
174
|
-
this.endDate = today.toISOString().split('T')[0];
|
|
175
|
-
|
|
176
|
-
// Initialize query parameters
|
|
177
|
-
this.orderQueryParams = this.createQueryParams();
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
ngOnInit() {
|
|
181
|
-
// Component initialization
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
private createQueryParams(): RunQueryParams {
|
|
185
|
-
return {
|
|
186
|
-
QueryID: 'CustomerOrdersWithDetails',
|
|
187
|
-
Parameters: {
|
|
188
|
-
StartDate: this.startDate,
|
|
189
|
-
EndDate: this.endDate,
|
|
190
|
-
Status: 'Active'
|
|
191
|
-
},
|
|
192
|
-
MaxRows: 1000
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
updateQueryParams() {
|
|
197
|
-
this.orderQueryParams = this.createQueryParams();
|
|
198
|
-
// The grid will automatically refresh when params change
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
refreshData() {
|
|
202
|
-
// Method 1: Using ViewChild reference
|
|
203
|
-
if (this.orderGrid) {
|
|
204
|
-
this.orderGrid.RefreshFromSavedParams();
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Method 2: Update params to trigger refresh
|
|
208
|
-
// this.orderQueryParams = { ...this.createQueryParams() };
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
onOrderRowClicked(event: GridRowClickedEvent) {
|
|
212
|
-
console.log('Order clicked:', event);
|
|
213
|
-
this.selectedOrder = event;
|
|
214
|
-
|
|
215
|
-
// You could navigate to a detail page here
|
|
216
|
-
// this.router.navigate(['/orders', event.entityId]);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
getOrderField(fieldName: string): string {
|
|
220
|
-
if (!this.selectedOrder) return '';
|
|
221
|
-
|
|
222
|
-
const field = this.selectedOrder.KeyValuePairs.find(kvp => kvp.Key === fieldName);
|
|
223
|
-
return field?.Value || '';
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
getOrderAmount(): number {
|
|
227
|
-
const amount = this.getOrderField('TotalAmount');
|
|
228
|
-
return amount ? parseFloat(amount) : 0;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
57
|
+
const queryParams: RunQueryParams = {
|
|
58
|
+
QueryID: 'some-query-id'
|
|
59
|
+
};
|
|
231
60
|
```
|
|
232
61
|
|
|
233
62
|
## API Reference
|
|
234
63
|
|
|
235
|
-
### Component Selector
|
|
236
|
-
`mj-query-grid`
|
|
237
|
-
|
|
238
64
|
### Inputs
|
|
239
65
|
|
|
240
|
-
|
|
|
241
|
-
|
|
242
|
-
| `Params` | `RunQueryParams
|
|
66
|
+
| Property | Type | Default | Description |
|
|
67
|
+
|----------|------|---------|-------------|
|
|
68
|
+
| `Params` | `RunQueryParams` | `undefined` | Query parameters including QueryID |
|
|
243
69
|
| `BottomMargin` | `number` | `0` | Bottom margin in pixels |
|
|
244
|
-
| `InEditMode` | `boolean` | `false` | Whether
|
|
245
|
-
| `EditMode` | `
|
|
246
|
-
| `AutoNavigate` | `boolean` | `true` |
|
|
247
|
-
| `AllowLoad` | `boolean` | `true` |
|
|
70
|
+
| `InEditMode` | `boolean` | `false` | Whether edit mode is active |
|
|
71
|
+
| `EditMode` | `'None' \| 'Save' \| 'Queue'` | `'None'` | Edit behavior mode |
|
|
72
|
+
| `AutoNavigate` | `boolean` | `true` | Auto-navigate on row click |
|
|
73
|
+
| `AllowLoad` | `boolean` | `true` | Deferred loading control |
|
|
248
74
|
|
|
249
75
|
### Outputs
|
|
250
76
|
|
|
251
|
-
|
|
|
252
|
-
|
|
77
|
+
| Event | Type | Description |
|
|
78
|
+
|-------|------|-------------|
|
|
253
79
|
| `rowClicked` | `EventEmitter<GridRowClickedEvent>` | Emitted when a grid row is clicked |
|
|
254
80
|
|
|
255
81
|
### Public Methods
|
|
256
82
|
|
|
257
|
-
| Method |
|
|
258
|
-
|
|
259
|
-
| `Refresh` |
|
|
260
|
-
| `RefreshFromSavedParams` |
|
|
261
|
-
| `doExcelExport` |
|
|
83
|
+
| Method | Description |
|
|
84
|
+
|--------|-------------|
|
|
85
|
+
| `Refresh(params)` | Runs the query and refreshes the grid |
|
|
86
|
+
| `RefreshFromSavedParams()` | Re-runs with previously saved parameters |
|
|
87
|
+
| `doExcelExport()` | Exports current data to Excel |
|
|
262
88
|
|
|
263
|
-
|
|
89
|
+
## Migration to @memberjunction/ng-query-viewer
|
|
264
90
|
|
|
265
|
-
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
entityName: string;
|
|
270
|
-
KeyValuePairs: KeyValuePair[];
|
|
271
|
-
}
|
|
91
|
+
Replace:
|
|
92
|
+
```html
|
|
93
|
+
<mj-query-grid [Params]="params" (rowClicked)="onRow($event)">
|
|
94
|
+
</mj-query-grid>
|
|
272
95
|
```
|
|
273
96
|
|
|
274
|
-
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
Parameters?: Record<string, any>; // Optional templated query parameters
|
|
282
|
-
MaxRows?: number; // Maximum rows to return
|
|
283
|
-
StartRow?: number; // Row offset for pagination
|
|
284
|
-
}
|
|
97
|
+
With:
|
|
98
|
+
```html
|
|
99
|
+
<mj-query-viewer
|
|
100
|
+
[QueryId]="queryId"
|
|
101
|
+
[AutoRun]="true"
|
|
102
|
+
(EntityLinkClick)="onEntityLink($event)">
|
|
103
|
+
</mj-query-viewer>
|
|
285
104
|
```
|
|
286
105
|
|
|
287
|
-
## Grid Configuration
|
|
288
|
-
|
|
289
|
-
The component uses Kendo UI Grid with the following configuration:
|
|
290
|
-
|
|
291
|
-
- **Virtual Scrolling**: Enabled for performance with large datasets
|
|
292
|
-
- **Row Height**: 36px fixed height for virtual scrolling
|
|
293
|
-
- **Page Size**: 40 rows per page
|
|
294
|
-
- **Features**: Sorting, resizing, reordering, and selection enabled
|
|
295
|
-
- **Toolbar**: Excel export and refresh buttons
|
|
296
|
-
|
|
297
|
-
## Excel Export
|
|
298
|
-
|
|
299
|
-
The Excel export feature:
|
|
300
|
-
- Exports all loaded data (not just visible page)
|
|
301
|
-
- Automatically names file as `{QueryID}_Query.xlsx`
|
|
302
|
-
- Shows progress notifications during export
|
|
303
|
-
- Dynamically generates columns based on query results
|
|
304
|
-
|
|
305
|
-
## Styling and Layout
|
|
306
|
-
|
|
307
|
-
The component uses:
|
|
308
|
-
- `mjFillContainer` directive to fill available space
|
|
309
|
-
- Kendo UI Grid default styling
|
|
310
|
-
- Font Awesome icons for buttons
|
|
311
|
-
- Customizable through CSS
|
|
312
|
-
|
|
313
106
|
## Dependencies
|
|
314
107
|
|
|
315
|
-
|
|
316
|
-
- `@angular
|
|
317
|
-
- `@angular
|
|
318
|
-
- `@angular/forms`: ^18.0.2
|
|
319
|
-
- `@angular/router`: ^18.0.2
|
|
320
|
-
- `@progress/kendo-angular-grid`: ^16.2.0
|
|
321
|
-
- `@progress/kendo-angular-buttons`: ^16.2.0
|
|
322
|
-
- `@progress/kendo-angular-dialog`: ^16.2.0
|
|
323
|
-
|
|
324
|
-
### Runtime Dependencies
|
|
325
|
-
- `@memberjunction/core`: For query execution and metadata
|
|
326
|
-
- `@memberjunction/core-entities`: For entity types
|
|
327
|
-
- `@memberjunction/global`: For global utilities and events
|
|
328
|
-
- `@memberjunction/ng-container-directives`: For layout directives
|
|
329
|
-
- `@memberjunction/ng-compare-records`: For record comparison
|
|
330
|
-
- `@memberjunction/ng-shared`: For shared Angular utilities
|
|
331
|
-
|
|
332
|
-
## Integration with MemberJunction
|
|
333
|
-
|
|
334
|
-
This component integrates seamlessly with the MemberJunction ecosystem:
|
|
335
|
-
|
|
336
|
-
1. **Query Execution**: Uses `RunQuery` class from `@memberjunction/core` to execute queries
|
|
337
|
-
2. **Metadata Support**: Leverages MemberJunction metadata system
|
|
338
|
-
3. **Event System**: Uses `MJGlobal` event system for notifications
|
|
339
|
-
4. **Layout Integration**: Works with MemberJunction container directives
|
|
340
|
-
|
|
341
|
-
## Best Practices
|
|
342
|
-
|
|
343
|
-
1. **Container Height**: Always wrap the component in a container with defined height for virtual scrolling
|
|
344
|
-
2. **Query Parameters**: Validate query parameters before passing to the component
|
|
345
|
-
3. **Error Handling**: The component shows error notifications automatically
|
|
346
|
-
4. **Performance**: Use `MaxRows` parameter for large datasets
|
|
347
|
-
5. **Deferred Loading**: Use `AllowLoad` input to control when data loads
|
|
348
|
-
|
|
349
|
-
## Troubleshooting
|
|
350
|
-
|
|
351
|
-
### Grid Not Displaying
|
|
352
|
-
- Ensure the parent container has a defined height
|
|
353
|
-
- Check that `Params` includes a valid `QueryID`
|
|
354
|
-
- Verify query permissions in MemberJunction
|
|
355
|
-
|
|
356
|
-
### Export Not Working
|
|
357
|
-
- Check browser permissions for file downloads
|
|
358
|
-
- Ensure data is loaded before attempting export
|
|
359
|
-
- Verify Excel export module is properly imported
|
|
360
|
-
|
|
361
|
-
### Performance Issues
|
|
362
|
-
- Use `MaxRows` to limit result set size
|
|
363
|
-
- Enable virtual scrolling (default)
|
|
364
|
-
- Consider server-side pagination for very large datasets
|
|
108
|
+
- [@memberjunction/core](../../MJCore/README.md) -- Metadata, RunQuery
|
|
109
|
+
- `@progress/kendo-angular-grid` -- Grid rendering
|
|
110
|
+
- `@progress/kendo-angular-excel-export` -- Excel export
|
|
365
111
|
|
|
366
|
-
##
|
|
112
|
+
## Related Packages
|
|
367
113
|
|
|
368
|
-
|
|
114
|
+
- [@memberjunction/ng-query-viewer](../query-viewer/README.md) -- Recommended replacement
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-query-grid",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.0",
|
|
4
4
|
"description": "MemberJunction: Angular Grid to display any MemberJunction Query",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"@progress/kendo-angular-dialog": "22.0.1"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@memberjunction/core": "4.
|
|
32
|
-
"@memberjunction/core-entities": "4.
|
|
33
|
-
"@memberjunction/global": "4.
|
|
34
|
-
"@memberjunction/ng-container-directives": "4.
|
|
35
|
-
"@memberjunction/ng-shared": "4.
|
|
31
|
+
"@memberjunction/core": "4.2.0",
|
|
32
|
+
"@memberjunction/core-entities": "4.2.0",
|
|
33
|
+
"@memberjunction/global": "4.2.0",
|
|
34
|
+
"@memberjunction/ng-container-directives": "4.2.0",
|
|
35
|
+
"@memberjunction/ng-shared": "4.2.0",
|
|
36
36
|
"@progress/kendo-angular-excel-export": "22.0.1",
|
|
37
37
|
"tslib": "^2.8.1"
|
|
38
38
|
},
|