@memberjunction/ng-list-detail-grid 2.42.1 → 2.44.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 +261 -45
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,20 +1,42 @@
|
|
|
1
1
|
# @memberjunction/ng-list-detail-grid
|
|
2
2
|
|
|
3
|
-
The `@memberjunction/ng-list-detail-grid` package provides
|
|
3
|
+
The `@memberjunction/ng-list-detail-grid` package provides a powerful Angular grid component for displaying and managing list details in the MemberJunction Explorer application. It enables users to view, edit, compare, merge, and export records from any MemberJunction entity with comprehensive data management capabilities.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- Display
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
7
|
+
- **Data Display & Navigation**
|
|
8
|
+
- Display records from both saved views and dynamic queries
|
|
9
|
+
- Virtual scrolling with pagination for optimal performance
|
|
10
|
+
- Automatic column formatting based on entity metadata
|
|
11
|
+
- Support for boolean values with checkmark display
|
|
12
|
+
- Configurable bottom margin for layout flexibility
|
|
13
|
+
|
|
14
|
+
- **Editing Capabilities**
|
|
15
|
+
- Inline cell editing with validation
|
|
16
|
+
- Three edit modes: None, Save (immediate), and Queue (batch)
|
|
17
|
+
- Keyboard navigation support (ESC to cancel edits)
|
|
18
|
+
- Automatic data type detection for appropriate editors
|
|
19
|
+
- Revert pending changes functionality
|
|
20
|
+
|
|
21
|
+
- **Column Management**
|
|
22
|
+
- Column reordering via drag and drop
|
|
23
|
+
- Column resizing with persistence
|
|
24
|
+
- Multi-column sorting
|
|
25
|
+
- Hide/show columns
|
|
26
|
+
- Automatic column width based on entity metadata
|
|
27
|
+
|
|
28
|
+
- **Record Operations**
|
|
29
|
+
- Compare multiple records side-by-side
|
|
30
|
+
- Merge duplicate records with field-level selection
|
|
31
|
+
- Find potential duplicates within datasets
|
|
32
|
+
- Multi-record selection with checkbox mode
|
|
33
|
+
- Excel export with full dataset support
|
|
34
|
+
|
|
35
|
+
- **Integration Features**
|
|
36
|
+
- Deep integration with MemberJunction metadata system
|
|
37
|
+
- Automatic permission checking for CRUD operations
|
|
38
|
+
- State persistence for saved views
|
|
39
|
+
- Event-driven architecture for parent component interaction
|
|
18
40
|
|
|
19
41
|
## Installation
|
|
20
42
|
|
|
@@ -151,53 +173,83 @@ export class MyListViewComponent {
|
|
|
151
173
|
|
|
152
174
|
### ListDetailGridComponent
|
|
153
175
|
|
|
176
|
+
The main component that renders the grid and handles all data operations.
|
|
177
|
+
|
|
154
178
|
#### Inputs
|
|
155
179
|
|
|
156
180
|
| Name | Type | Default | Description |
|
|
157
181
|
|------|------|---------|-------------|
|
|
158
|
-
| `Params` | `RunViewParams` | `undefined` | Parameters for the view to display |
|
|
159
|
-
| `BottomMargin` | `number` | `0` | Margin to apply at the bottom of the grid |
|
|
182
|
+
| `Params` | `RunViewParams` | `undefined` | Parameters for the view to display. Can include ViewID, ViewName, ViewEntity, or EntityName with ExtraFilter |
|
|
183
|
+
| `BottomMargin` | `number` | `0` | Margin to apply at the bottom of the grid in pixels |
|
|
160
184
|
| `InEditMode` | `boolean` | `false` | Whether the grid is currently in edit mode |
|
|
161
|
-
| `EditMode` | `"None" \| "Save" \| "Queue"` | `"None"` | Mode for handling edited records |
|
|
162
|
-
| `AutoNavigate` | `boolean` | `true` | Whether to auto-navigate to a record when clicked |
|
|
163
|
-
| `AllowLoad` | `boolean` | `true` | Whether to allow loading the data |
|
|
185
|
+
| `EditMode` | `"None" \| "Save" \| "Queue"` | `"None"` | Mode for handling edited records. "Save" saves immediately, "Queue" batches changes |
|
|
186
|
+
| `AutoNavigate` | `boolean` | `true` | Whether to auto-navigate to a record detail page when clicked |
|
|
187
|
+
| `AllowLoad` | `boolean` | `true` | Whether to allow loading the data. Useful for deferring load until ready |
|
|
164
188
|
|
|
165
189
|
#### Outputs
|
|
166
190
|
|
|
167
191
|
| Name | Type | Description |
|
|
168
192
|
|------|------|-------------|
|
|
169
|
-
| `rowClicked` | `EventEmitter<GridRowClickedEvent>` | Emitted when a row is clicked |
|
|
170
|
-
| `rowEdited` | `EventEmitter<GridRowEditedEvent>` | Emitted when a row is edited |
|
|
193
|
+
| `rowClicked` | `EventEmitter<GridRowClickedEvent>` | Emitted when a row is clicked, includes entity info and composite key |
|
|
194
|
+
| `rowEdited` | `EventEmitter<GridRowEditedEvent>` | Emitted when a row is edited, includes the record and save status |
|
|
171
195
|
|
|
172
|
-
#### Methods
|
|
196
|
+
#### Public Methods
|
|
173
197
|
|
|
174
198
|
| Name | Parameters | Return Type | Description |
|
|
175
199
|
|------|------------|-------------|-------------|
|
|
176
|
-
| `Refresh` | `params: RunViewParams` | `Promise<void>` | Refreshes the grid data |
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
200
|
+
| `Refresh` | `params: RunViewParams` | `Promise<void>` | Refreshes the grid data with new parameters |
|
|
201
|
+
| `RefreshFromSavedParams` | None | `Promise<void>` | Refreshes using the current saved parameters |
|
|
202
|
+
| `EditingComplete` | None | `Promise<boolean>` | Completes the current edit operation and closes any open cells |
|
|
203
|
+
| `RevertPendingChanges` | None | `void` | Reverts all pending changes in Queue mode |
|
|
204
|
+
| `enableCheckbox` | `cancel: boolean, type: 'merge' \| 'compare' \| 'duplicate' \| ''` | `void` | Enables/disables selection mode for operations |
|
|
205
|
+
| `doExcelExport` | None | `Promise<void>` | Exports the entire dataset to Excel |
|
|
206
|
+
| `IsDynamicView` | None | `boolean` | Returns true if using a dynamic view (not saved) |
|
|
207
|
+
|
|
208
|
+
#### Public Properties
|
|
209
|
+
|
|
210
|
+
| Name | Type | Description |
|
|
211
|
+
|------|------|-------------|
|
|
212
|
+
| `PendingRecords` | `GridPendingRecordItem[]` | Array of records with pending changes in Queue mode |
|
|
213
|
+
| `ViewID` | `string` | The ID of the current view (if using a saved view) |
|
|
214
|
+
| `viewColumns` | `ViewColumnInfo[]` | Array of all column configurations |
|
|
215
|
+
| `visibleColumns` | `ViewColumnInfo[]` | Array of visible (non-hidden) columns |
|
|
216
|
+
| `viewExecutionTime` | `number` | Time taken to execute the view query (in seconds) |
|
|
181
217
|
|
|
182
|
-
###
|
|
218
|
+
### Type Definitions
|
|
183
219
|
|
|
184
220
|
#### GridRowClickedEvent
|
|
185
221
|
|
|
222
|
+
Emitted when a user clicks on a grid row.
|
|
223
|
+
|
|
186
224
|
```typescript
|
|
187
225
|
type GridRowClickedEvent = {
|
|
188
|
-
entityId: string;
|
|
189
|
-
entityName: string;
|
|
190
|
-
CompositeKey: CompositeKey;
|
|
226
|
+
entityId: string; // The ID of the entity definition
|
|
227
|
+
entityName: string; // The name of the entity
|
|
228
|
+
CompositeKey: CompositeKey; // Composite key object for the clicked record
|
|
191
229
|
}
|
|
192
230
|
```
|
|
193
231
|
|
|
194
232
|
#### GridRowEditedEvent
|
|
195
233
|
|
|
234
|
+
Emitted when a row edit operation completes.
|
|
235
|
+
|
|
196
236
|
```typescript
|
|
197
237
|
type GridRowEditedEvent = {
|
|
198
|
-
record: BaseEntity;
|
|
199
|
-
row: number;
|
|
200
|
-
saved: boolean;
|
|
238
|
+
record: BaseEntity; // The entity record that was edited
|
|
239
|
+
row: number; // The row index in the grid
|
|
240
|
+
saved: boolean; // Whether the save was successful (always false in Queue mode)
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
#### GridPendingRecordItem
|
|
245
|
+
|
|
246
|
+
Represents a record with pending changes in Queue mode.
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
type GridPendingRecordItem = {
|
|
250
|
+
record: BaseEntity; // The entity record with changes
|
|
251
|
+
row: number; // The row index in the grid
|
|
252
|
+
dataItem: any; // The raw data item from the grid
|
|
201
253
|
}
|
|
202
254
|
```
|
|
203
255
|
|
|
@@ -221,24 +273,188 @@ modifyColumns() {
|
|
|
221
273
|
}
|
|
222
274
|
```
|
|
223
275
|
|
|
276
|
+
### Advanced Usage
|
|
277
|
+
|
|
278
|
+
#### Working with Dynamic Views
|
|
279
|
+
|
|
280
|
+
For scenarios where you need to display data without a saved view:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// Dynamic view with custom filtering
|
|
284
|
+
const dynamicParams: RunViewParams = {
|
|
285
|
+
EntityName: 'Customers',
|
|
286
|
+
ExtraFilter: "Status='Active' AND Country='USA'",
|
|
287
|
+
OrderBy: 'CreatedAt DESC',
|
|
288
|
+
Skip: 0,
|
|
289
|
+
Take: 100
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
// Use with the grid
|
|
293
|
+
<mj-list-detail-grid [Params]="dynamicParams"></mj-list-detail-grid>
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
#### Handling Batch Edits
|
|
297
|
+
|
|
298
|
+
When using Queue mode for batch editing:
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
export class MyComponent {
|
|
302
|
+
@ViewChild(ListDetailGridComponent) grid!: ListDetailGridComponent;
|
|
303
|
+
|
|
304
|
+
async savePendingChanges() {
|
|
305
|
+
// Get all pending records
|
|
306
|
+
const pendingRecords = this.grid.PendingRecords;
|
|
307
|
+
|
|
308
|
+
// Save each record
|
|
309
|
+
for (const item of pendingRecords) {
|
|
310
|
+
const saved = await item.record.Save();
|
|
311
|
+
if (!saved) {
|
|
312
|
+
console.error('Failed to save record:', item.record.PrimaryKey);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Refresh the grid
|
|
317
|
+
await this.grid.RefreshFromSavedParams();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
cancelChanges() {
|
|
321
|
+
this.grid.RevertPendingChanges();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
#### Programmatic Record Operations
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
export class MyComponent {
|
|
330
|
+
@ViewChild(ListDetailGridComponent) grid!: ListDetailGridComponent;
|
|
331
|
+
|
|
332
|
+
// Start duplicate detection
|
|
333
|
+
async detectDuplicates() {
|
|
334
|
+
// Enable duplicate mode
|
|
335
|
+
this.grid.enableCheckbox(false, 'duplicate');
|
|
336
|
+
|
|
337
|
+
// Programmatically select records if needed
|
|
338
|
+
this.grid.selectedKeys = [0, 1, 2]; // Select first 3 records
|
|
339
|
+
|
|
340
|
+
// Trigger duplicate detection
|
|
341
|
+
await this.grid.findDuplicateRecords();
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Performance Optimization
|
|
347
|
+
|
|
348
|
+
The grid implements several performance optimizations:
|
|
349
|
+
|
|
350
|
+
1. **Virtual Scrolling**: Only renders visible rows, enabling smooth scrolling through large datasets
|
|
351
|
+
2. **Lazy Column Formatting**: Formats data only when needed for display
|
|
352
|
+
3. **Debounced View Saving**: Column and sort changes are saved after a 5-second delay to reduce API calls
|
|
353
|
+
4. **Efficient Data Loading**: Uses MemberJunction's RunView for optimized server-side queries
|
|
354
|
+
|
|
224
355
|
### Styling
|
|
225
356
|
|
|
226
357
|
The component uses the following CSS classes that can be customized:
|
|
227
358
|
|
|
228
359
|
- `.list-detail-grid-wrap`: Main container for the grid
|
|
360
|
+
- Column-specific styles are applied based on data types (right-aligned for numbers, left-aligned for text)
|
|
361
|
+
|
|
362
|
+
### Best Practices
|
|
363
|
+
|
|
364
|
+
1. **Use Saved Views When Possible**: Saved views persist user preferences and are more performant
|
|
365
|
+
2. **Choose Appropriate Edit Mode**:
|
|
366
|
+
- Use "Save" mode for immediate persistence
|
|
367
|
+
- Use "Queue" mode when users need to review changes before saving
|
|
368
|
+
3. **Handle Events Properly**: Always handle `rowEdited` events to provide user feedback
|
|
369
|
+
4. **Export Considerations**: Large exports may take time; the component shows notifications during export
|
|
370
|
+
5. **Permission Checking**: The component automatically checks entity permissions before allowing edits
|
|
371
|
+
|
|
372
|
+
## Integration with MemberJunction
|
|
373
|
+
|
|
374
|
+
This component deeply integrates with MemberJunction's metadata system:
|
|
375
|
+
|
|
376
|
+
- Automatically formats columns based on entity field metadata
|
|
377
|
+
- Respects entity permissions for CRUD operations
|
|
378
|
+
- Uses entity field validation rules
|
|
379
|
+
- Supports all MemberJunction field types including virtual fields
|
|
380
|
+
- Integrates with the MemberJunction audit log for exports
|
|
229
381
|
|
|
230
382
|
## Dependencies
|
|
231
383
|
|
|
232
|
-
|
|
233
|
-
-
|
|
234
|
-
-
|
|
235
|
-
-
|
|
236
|
-
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
-
|
|
240
|
-
-
|
|
241
|
-
-
|
|
242
|
-
-
|
|
243
|
-
-
|
|
244
|
-
-
|
|
384
|
+
### Angular Dependencies
|
|
385
|
+
- `@angular/common`: ^18.0.2
|
|
386
|
+
- `@angular/core`: ^18.0.2
|
|
387
|
+
- `@angular/forms`: ^18.0.2
|
|
388
|
+
- `@angular/router`: ^18.0.2
|
|
389
|
+
|
|
390
|
+
### MemberJunction Dependencies
|
|
391
|
+
- `@memberjunction/core`: ^2.43.0
|
|
392
|
+
- `@memberjunction/core-entities`: ^2.43.0
|
|
393
|
+
- `@memberjunction/global`: ^2.43.0
|
|
394
|
+
- `@memberjunction/ng-shared`: ^2.43.0
|
|
395
|
+
- `@memberjunction/ng-compare-records`: ^2.43.0
|
|
396
|
+
- `@memberjunction/ng-container-directives`: ^2.43.0
|
|
397
|
+
|
|
398
|
+
### Kendo UI Dependencies
|
|
399
|
+
- `@progress/kendo-angular-grid`: ^16.2.0
|
|
400
|
+
- `@progress/kendo-angular-layout`: ^16.2.0
|
|
401
|
+
- `@progress/kendo-angular-inputs`: ^16.2.0
|
|
402
|
+
- `@progress/kendo-angular-buttons`: ^16.2.0
|
|
403
|
+
- `@progress/kendo-angular-excel-export`: (via GridModule)
|
|
404
|
+
- `@progress/kendo-angular-dialog`: (via GridModule)
|
|
405
|
+
|
|
406
|
+
## Troubleshooting
|
|
407
|
+
|
|
408
|
+
### Common Issues
|
|
409
|
+
|
|
410
|
+
#### Grid Not Loading Data
|
|
411
|
+
- Ensure `AllowLoad` is set to `true` (default)
|
|
412
|
+
- Verify that `Params` contains valid view parameters
|
|
413
|
+
- Check console for API errors or permission issues
|
|
414
|
+
|
|
415
|
+
#### Edit Mode Not Working
|
|
416
|
+
- Verify the entity has `AllowUpdateAPI` set to true
|
|
417
|
+
- Check user permissions for the entity
|
|
418
|
+
- Ensure `EditMode` is set to either "Save" or "Queue"
|
|
419
|
+
|
|
420
|
+
#### Export Failing
|
|
421
|
+
- Check for large dataset timeouts
|
|
422
|
+
- Ensure user has appropriate permissions
|
|
423
|
+
- Verify the export audit log entry was created
|
|
424
|
+
|
|
425
|
+
#### Column Reordering Not Persisting
|
|
426
|
+
- Only works with saved views (not dynamic views)
|
|
427
|
+
- User must own the view to save changes
|
|
428
|
+
- Check for save errors in the console
|
|
429
|
+
|
|
430
|
+
### Debug Tips
|
|
431
|
+
|
|
432
|
+
1. Enable console logging to see detailed error messages
|
|
433
|
+
2. Check the Network tab for failed API calls
|
|
434
|
+
3. Verify entity metadata is loaded before grid initialization
|
|
435
|
+
4. Use `viewExecutionTime` property to identify slow queries
|
|
436
|
+
|
|
437
|
+
## Migration Guide
|
|
438
|
+
|
|
439
|
+
### From Earlier Versions
|
|
440
|
+
|
|
441
|
+
If upgrading from versions prior to 2.43.0:
|
|
442
|
+
|
|
443
|
+
1. Update all MemberJunction dependencies to matching versions
|
|
444
|
+
2. Update Angular to version 18
|
|
445
|
+
3. Update Kendo UI components to version 16.2.0
|
|
446
|
+
4. Review breaking changes in the CHANGELOG.md
|
|
447
|
+
|
|
448
|
+
## Contributing
|
|
449
|
+
|
|
450
|
+
When contributing to this package:
|
|
451
|
+
|
|
452
|
+
1. Follow the MemberJunction coding standards
|
|
453
|
+
2. Ensure all TypeScript compiles without errors
|
|
454
|
+
3. Update this README for any API changes
|
|
455
|
+
4. Add unit tests for new functionality
|
|
456
|
+
5. Update the CHANGELOG.md
|
|
457
|
+
|
|
458
|
+
## License
|
|
459
|
+
|
|
460
|
+
This package is part of the MemberJunction framework and follows the same [ISC License](../../../LICENSE).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-list-detail-grid",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.44.0",
|
|
4
4
|
"description": "MemberJunction: Angular Grid to display dynamic and saved List Details for any entity in MemberJunction.",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
"@angular/router": "18.0.2"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@memberjunction/core-entities": "2.
|
|
29
|
-
"@memberjunction/global": "2.
|
|
30
|
-
"@memberjunction/core": "2.
|
|
31
|
-
"@memberjunction/ng-shared": "2.
|
|
32
|
-
"@memberjunction/ng-compare-records": "2.
|
|
33
|
-
"@memberjunction/ng-container-directives": "2.
|
|
28
|
+
"@memberjunction/core-entities": "2.44.0",
|
|
29
|
+
"@memberjunction/global": "2.44.0",
|
|
30
|
+
"@memberjunction/core": "2.44.0",
|
|
31
|
+
"@memberjunction/ng-shared": "2.44.0",
|
|
32
|
+
"@memberjunction/ng-compare-records": "2.44.0",
|
|
33
|
+
"@memberjunction/ng-container-directives": "2.44.0",
|
|
34
34
|
"@progress/kendo-angular-grid": "16.2.0",
|
|
35
35
|
"@progress/kendo-angular-layout": "16.2.0",
|
|
36
36
|
"@progress/kendo-angular-inputs": "16.2.0",
|