2.48.0 • Published 5 months ago

@memberjunction/ng-list-detail-grid v2.48.0

Weekly downloads
-
License
ISC
Repository
-
Last release
5 months ago

@memberjunction/ng-list-detail-grid

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.

Features

  • Data Display & Navigation

    • Display records from both saved views and dynamic queries
    • Virtual scrolling with pagination for optimal performance
    • Automatic column formatting based on entity metadata
    • Support for boolean values with checkmark display
    • Configurable bottom margin for layout flexibility
  • Editing Capabilities

    • Inline cell editing with validation
    • Three edit modes: None, Save (immediate), and Queue (batch)
    • Keyboard navigation support (ESC to cancel edits)
    • Automatic data type detection for appropriate editors
    • Revert pending changes functionality
  • Column Management

    • Column reordering via drag and drop
    • Column resizing with persistence
    • Multi-column sorting
    • Hide/show columns
    • Automatic column width based on entity metadata
  • Record Operations

    • Compare multiple records side-by-side
    • Merge duplicate records with field-level selection
    • Find potential duplicates within datasets
    • Multi-record selection with checkbox mode
    • Excel export with full dataset support
  • Integration Features

    • Deep integration with MemberJunction metadata system
    • Automatic permission checking for CRUD operations
    • State persistence for saved views
    • Event-driven architecture for parent component interaction

Installation

npm install @memberjunction/ng-list-detail-grid

Requirements

  • Angular 18+
  • @memberjunction/core
  • @memberjunction/core-entities
  • @memberjunction/ng-compare-records
  • @memberjunction/ng-container-directives
  • @progress/kendo-angular-grid
  • @progress/kendo-angular-layout
  • @progress/kendo-angular-inputs
  • @progress/kendo-angular-buttons

Usage

Basic Setup

First, import the ListDetailGridModule in your module:

import { ListDetailGridModule } from '@memberjunction/ng-list-detail-grid';

@NgModule({
  imports: [
    // other imports...
    ListDetailGridModule
  ],
})
export class YourModule { }

Basic Usage

Use the component in your template:

<mj-list-detail-grid
  [Params]="viewParams"
  [BottomMargin]="15"
  [AutoNavigate]="true"
  (rowClicked)="onRowClicked($event)"
  (rowEdited)="onRowEdited($event)">
</mj-list-detail-grid>

In your component:

import { Component } from '@angular/core';
import { RunViewParams } from '@memberjunction/core';
import { GridRowClickedEvent, GridRowEditedEvent } from '@memberjunction/ng-list-detail-grid';

@Component({
  selector: 'app-my-list-view',
  templateUrl: './my-list-view.component.html',
})
export class MyListViewComponent {
  viewParams: RunViewParams = {
    EntityName: 'Lists',
    ExtraFilter: "Name LIKE '%Customer%'",
    Skip: 0,
    Take: 40
  };
  
  onRowClicked(event: GridRowClickedEvent) {
    console.log('Row clicked:', event);
    // Access event.entityName, event.entityId, event.CompositeKey
  }
  
  onRowEdited(event: GridRowEditedEvent) {
    console.log('Row edited:', event);
    // Access event.record, event.row, event.saved
  }
}

Editing Mode

Enable inline editing in the grid:

<mj-list-detail-grid
  [Params]="viewParams"
  [InEditMode]="false"
  [EditMode]="'Save'"
  (rowEdited)="onRowEdited($event)">
</mj-list-detail-grid>

The EditMode property supports three values:

  • "None" - Editing is disabled
  • "Save" - Changes are saved immediately
  • "Queue" - Changes are queued for later saving

Record Operations

The grid supports comparing, merging, and finding duplicates:

// In your component
import { ViewChild } from '@angular/core';
import { ListDetailGridComponent } from '@memberjunction/ng-list-detail-grid';

@Component({
  // ...
})
export class MyListViewComponent {
  @ViewChild(ListDetailGridComponent) listDetailGrid!: ListDetailGridComponent;
  
  // Start compare mode
  startCompare() {
    this.listDetailGrid.enableCheckbox(false, 'compare');
  }
  
  // Start merge mode
  startMerge() {
    this.listDetailGrid.enableCheckbox(false, 'merge');
  }
  
  // Start duplicate detection
  findDuplicates() {
    this.listDetailGrid.enableCheckbox(false, 'duplicate');
  }
}

API Reference

ListDetailGridComponent

The main component that renders the grid and handles all data operations.

Inputs

NameTypeDefaultDescription
ParamsRunViewParamsundefinedParameters for the view to display. Can include ViewID, ViewName, ViewEntity, or EntityName with ExtraFilter
BottomMarginnumber0Margin to apply at the bottom of the grid in pixels
InEditModebooleanfalseWhether the grid is currently in edit mode
EditMode"None" \| "Save" \| "Queue""None"Mode for handling edited records. "Save" saves immediately, "Queue" batches changes
AutoNavigatebooleantrueWhether to auto-navigate to a record detail page when clicked
AllowLoadbooleantrueWhether to allow loading the data. Useful for deferring load until ready

Outputs

NameTypeDescription
rowClickedEventEmitter<GridRowClickedEvent>Emitted when a row is clicked, includes entity info and composite key
rowEditedEventEmitter<GridRowEditedEvent>Emitted when a row is edited, includes the record and save status

Public Methods

NameParametersReturn TypeDescription
Refreshparams: RunViewParamsPromise<void>Refreshes the grid data with new parameters
RefreshFromSavedParamsNonePromise<void>Refreshes using the current saved parameters
EditingCompleteNonePromise<boolean>Completes the current edit operation and closes any open cells
RevertPendingChangesNonevoidReverts all pending changes in Queue mode
enableCheckboxcancel: boolean, type: 'merge' \| 'compare' \| 'duplicate' \| ''voidEnables/disables selection mode for operations
doExcelExportNonePromise<void>Exports the entire dataset to Excel
IsDynamicViewNonebooleanReturns true if using a dynamic view (not saved)

Public Properties

NameTypeDescription
PendingRecordsGridPendingRecordItem[]Array of records with pending changes in Queue mode
ViewIDstringThe ID of the current view (if using a saved view)
viewColumnsViewColumnInfo[]Array of all column configurations
visibleColumnsViewColumnInfo[]Array of visible (non-hidden) columns
viewExecutionTimenumberTime taken to execute the view query (in seconds)

Type Definitions

GridRowClickedEvent

Emitted when a user clicks on a grid row.

type GridRowClickedEvent = {
  entityId: string;         // The ID of the entity definition
  entityName: string;       // The name of the entity
  CompositeKey: CompositeKey; // Composite key object for the clicked record
}

GridRowEditedEvent

Emitted when a row edit operation completes.

type GridRowEditedEvent = {
  record: BaseEntity;  // The entity record that was edited
  row: number;         // The row index in the grid
  saved: boolean;      // Whether the save was successful (always false in Queue mode)
}

GridPendingRecordItem

Represents a record with pending changes in Queue mode.

type GridPendingRecordItem = {
  record: BaseEntity;  // The entity record with changes
  row: number;         // The row index in the grid
  dataItem: any;       // The raw data item from the grid
}

Customization

Column Customization

The grid automatically formats columns based on entity metadata, but you can customize the formatting by modifying the view columns:

// In your component
modifyColumns() {
  const columns = this.listDetailGrid.viewColumns;
  // Customize columns here
  columns.forEach(col => {
    if (col.Name === 'Priority') {
      col.width = 80;
    }
  });
  this.listDetailGrid.Refresh(this.listDetailGrid.Params!);
}

Advanced Usage

Working with Dynamic Views

For scenarios where you need to display data without a saved view:

// Dynamic view with custom filtering
const dynamicParams: RunViewParams = {
  EntityName: 'Customers',
  ExtraFilter: "Status='Active' AND Country='USA'",
  OrderBy: 'CreatedAt DESC',
  Skip: 0,
  Take: 100
};

// Use with the grid
<mj-list-detail-grid [Params]="dynamicParams"></mj-list-detail-grid>

Handling Batch Edits

When using Queue mode for batch editing:

export class MyComponent {
  @ViewChild(ListDetailGridComponent) grid!: ListDetailGridComponent;
  
  async savePendingChanges() {
    // Get all pending records
    const pendingRecords = this.grid.PendingRecords;
    
    // Save each record
    for (const item of pendingRecords) {
      const saved = await item.record.Save();
      if (!saved) {
        console.error('Failed to save record:', item.record.PrimaryKey);
      }
    }
    
    // Refresh the grid
    await this.grid.RefreshFromSavedParams();
  }
  
  cancelChanges() {
    this.grid.RevertPendingChanges();
  }
}

Programmatic Record Operations

export class MyComponent {
  @ViewChild(ListDetailGridComponent) grid!: ListDetailGridComponent;
  
  // Start duplicate detection
  async detectDuplicates() {
    // Enable duplicate mode
    this.grid.enableCheckbox(false, 'duplicate');
    
    // Programmatically select records if needed
    this.grid.selectedKeys = [0, 1, 2]; // Select first 3 records
    
    // Trigger duplicate detection
    await this.grid.findDuplicateRecords();
  }
}

Performance Optimization

The grid implements several performance optimizations:

  1. Virtual Scrolling: Only renders visible rows, enabling smooth scrolling through large datasets
  2. Lazy Column Formatting: Formats data only when needed for display
  3. Debounced View Saving: Column and sort changes are saved after a 5-second delay to reduce API calls
  4. Efficient Data Loading: Uses MemberJunction's RunView for optimized server-side queries

Styling

The component uses the following CSS classes that can be customized:

  • .list-detail-grid-wrap: Main container for the grid
  • Column-specific styles are applied based on data types (right-aligned for numbers, left-aligned for text)

Best Practices

  1. Use Saved Views When Possible: Saved views persist user preferences and are more performant
  2. Choose Appropriate Edit Mode:
    • Use "Save" mode for immediate persistence
    • Use "Queue" mode when users need to review changes before saving
  3. Handle Events Properly: Always handle rowEdited events to provide user feedback
  4. Export Considerations: Large exports may take time; the component shows notifications during export
  5. Permission Checking: The component automatically checks entity permissions before allowing edits

Integration with MemberJunction

This component deeply integrates with MemberJunction's metadata system:

  • Automatically formats columns based on entity field metadata
  • Respects entity permissions for CRUD operations
  • Uses entity field validation rules
  • Supports all MemberJunction field types including virtual fields
  • Integrates with the MemberJunction audit log for exports

Dependencies

Angular Dependencies

  • @angular/common: ^18.0.2
  • @angular/core: ^18.0.2
  • @angular/forms: ^18.0.2
  • @angular/router: ^18.0.2

MemberJunction Dependencies

  • @memberjunction/core: ^2.43.0
  • @memberjunction/core-entities: ^2.43.0
  • @memberjunction/global: ^2.43.0
  • @memberjunction/ng-shared: ^2.43.0
  • @memberjunction/ng-compare-records: ^2.43.0
  • @memberjunction/ng-container-directives: ^2.43.0

Kendo UI Dependencies

  • @progress/kendo-angular-grid: ^16.2.0
  • @progress/kendo-angular-layout: ^16.2.0
  • @progress/kendo-angular-inputs: ^16.2.0
  • @progress/kendo-angular-buttons: ^16.2.0
  • @progress/kendo-angular-excel-export: (via GridModule)
  • @progress/kendo-angular-dialog: (via GridModule)

Troubleshooting

Common Issues

Grid Not Loading Data

  • Ensure AllowLoad is set to true (default)
  • Verify that Params contains valid view parameters
  • Check console for API errors or permission issues

Edit Mode Not Working

  • Verify the entity has AllowUpdateAPI set to true
  • Check user permissions for the entity
  • Ensure EditMode is set to either "Save" or "Queue"

Export Failing

  • Check for large dataset timeouts
  • Ensure user has appropriate permissions
  • Verify the export audit log entry was created

Column Reordering Not Persisting

  • Only works with saved views (not dynamic views)
  • User must own the view to save changes
  • Check for save errors in the console

Debug Tips

  1. Enable console logging to see detailed error messages
  2. Check the Network tab for failed API calls
  3. Verify entity metadata is loaded before grid initialization
  4. Use viewExecutionTime property to identify slow queries

Migration Guide

From Earlier Versions

If upgrading from versions prior to 2.43.0:

  1. Update all MemberJunction dependencies to matching versions
  2. Update Angular to version 18
  3. Update Kendo UI components to version 16.2.0
  4. Review breaking changes in the CHANGELOG.md

Contributing

When contributing to this package:

  1. Follow the MemberJunction coding standards
  2. Ensure all TypeScript compiles without errors
  3. Update this README for any API changes
  4. Add unit tests for new functionality
  5. Update the CHANGELOG.md

License

This package is part of the MemberJunction framework and follows the same ISC License.

2.27.1

8 months ago

2.23.2

9 months ago

2.46.0

5 months ago

2.23.1

9 months ago

2.27.0

8 months ago

2.34.0

6 months ago

2.30.0

8 months ago

2.19.4

9 months ago

2.19.5

9 months ago

2.19.2

9 months ago

2.19.3

9 months ago

2.19.0

9 months ago

2.19.1

9 months ago

2.15.2

10 months ago

2.34.2

6 months ago

2.34.1

6 months ago

2.15.1

10 months ago

2.38.0

6 months ago

2.45.0

5 months ago

2.22.1

9 months ago

2.22.0

9 months ago

2.41.0

5 months ago

2.22.2

9 months ago

2.26.1

8 months ago

2.26.0

9 months ago

2.33.0

6 months ago

2.18.3

10 months ago

2.18.1

10 months ago

2.18.2

10 months ago

2.18.0

10 months ago

2.37.1

6 months ago

2.37.0

6 months ago

2.14.0

10 months ago

2.21.0

9 months ago

2.44.0

5 months ago

2.40.0

6 months ago

2.29.0

8 months ago

2.29.2

8 months ago

2.29.1

8 months ago

2.25.0

9 months ago

2.48.0

5 months ago

2.32.0

7 months ago

2.32.2

7 months ago

2.32.1

7 months ago

2.17.0

10 months ago

2.13.4

10 months ago

2.36.0

6 months ago

2.13.2

11 months ago

2.13.3

10 months ago

2.13.0

11 months ago

2.36.1

6 months ago

2.13.1

11 months ago

2.43.0

5 months ago

2.20.2

9 months ago

2.20.3

9 months ago

2.20.0

9 months ago

2.20.1

9 months ago

2.28.0

8 months ago

2.47.0

5 months ago

2.24.1

9 months ago

2.24.0

9 months ago

2.31.0

7 months ago

2.12.0

12 months ago

2.39.0

6 months ago

2.16.1

10 months ago

2.35.1

6 months ago

2.35.0

6 months ago

2.16.0

10 months ago

2.42.1

5 months ago

2.42.0

5 months ago

2.23.0

9 months ago

2.11.0

1 year ago

2.10.0

1 year ago

2.9.0

1 year ago

2.8.0

1 year ago

2.7.0

1 year ago

2.6.1

1 year ago

2.5.2

1 year ago

2.6.0

1 year ago

2.7.1

1 year ago

2.5.1

1 year ago

2.5.0

1 year ago

2.4.1

1 year ago

2.4.0

1 year ago

2.3.3

1 year ago

2.3.2

1 year ago

2.3.1

1 year ago

2.3.0

1 year ago

2.2.1

1 year ago

2.2.0

1 year ago

2.1.5

1 year ago

2.1.4

1 year ago

2.1.3

1 year ago

2.1.2

1 year ago

2.1.1

1 year ago

2.0.0

1 year ago

1.8.1

1 year ago

1.8.0

1 year ago

1.7.1

1 year ago

1.7.0

1 year ago

1.6.1

1 year ago

1.6.0

1 year ago

1.5.3

1 year ago

1.5.2

1 year ago

1.5.1

1 year ago

1.5.0

1 year ago

1.4.1

1 year ago