2.48.0 • Published 5 months ago

@memberjunction/ng-compare-records v2.48.0

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

@memberjunction/ng-compare-records

The @memberjunction/ng-compare-records package provides a powerful Angular component for comparing multiple records of the same entity type. It displays records side-by-side in a grid format, highlighting differences between them, and optionally allows selecting values from different records to create a composite record.

Features

  • Side-by-side comparison of multiple entity records
  • Option to show only differences between records
  • Option to suppress fields with blank values
  • Highlighting of selected record and field values
  • "Selection mode" that allows picking values from different records
  • Automatic record dependency detection
  • Support for composite primary keys
  • Responsive grid with virtual scrolling
  • Field formatting according to entity metadata
  • Automatic data loading for incomplete records
  • Read-only field indication with italic styling
  • Header click to select base record in selection mode

Installation

npm install @memberjunction/ng-compare-records

Requirements

  • Angular 18+
  • @memberjunction/core
  • @memberjunction/core-entities
  • @progress/kendo-angular-grid
  • @progress/kendo-angular-inputs
  • @progress/kendo-angular-label

Usage

Basic Setup

First, import the CompareRecordsModule in your module:

import { CompareRecordsModule } from '@memberjunction/ng-compare-records';

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

Basic Usage

Use the component in your template for simple record comparison:

<mj-compare-records
  [recordsToCompare]="recordsToCompare"
  [entityName]="entityName">
</mj-compare-records>

In your component:

import { Component, OnInit } from '@angular/core';
import { BaseEntity, Metadata } from '@memberjunction/core';

@Component({
  selector: 'app-compare-example',
  templateUrl: './compare-example.component.html',
})
export class CompareExampleComponent implements OnInit {
  recordsToCompare: BaseEntity[] = [];
  entityName: string = 'Customer';

  constructor(private metadata: Metadata) {}

  async ngOnInit() {
    // Load records to compare
    const customer1 = await this.metadata.GetEntityObject('Customer', 1);
    const customer2 = await this.metadata.GetEntityObject('Customer', 2);
    const customer3 = await this.metadata.GetEntityObject('Customer', 3);
    
    await Promise.all([
      customer1.Load(),
      customer2.Load(),
      customer3.Load()
    ]);
    
    this.recordsToCompare = [customer1, customer2, customer3];
  }
}

Advanced Usage with Selection Mode

When you need to allow users to select values from different records to create a composite record:

<mj-compare-records
  [recordsToCompare]="recordsToCompare"
  [entityName]="entityName"
  [selectionMode]="true">
</mj-compare-records>

In your component:

import { Component, OnInit, ViewChild } from '@angular/core';
import { BaseEntity, Metadata } from '@memberjunction/core';
import { CompareRecordsComponent } from '@memberjunction/ng-compare-records';

@Component({
  selector: 'app-advanced-compare',
  templateUrl: './advanced-compare.component.html',
})
export class AdvancedCompareComponent implements OnInit {
  @ViewChild(CompareRecordsComponent) compareComponent!: CompareRecordsComponent;
  
  recordsToCompare: BaseEntity[] = [];
  entityName: string = 'Product';

  constructor(private metadata: Metadata) {}

  async ngOnInit() {
    // Load records to compare
    // ... Load your records
  }

  async createCompositeRecord() {
    // Get the base record (selected record)
    const baseRecord = this.recordsToCompare.find(r => 
      r.PrimaryKey.Equals(this.compareComponent.selectedRecordCompositeKey)
    );
    
    if (baseRecord) {
      // Create a new entity object
      const newRecord = await this.metadata.GetEntityObject(this.entityName);
      
      // Copy all values from the base record
      for (const field of baseRecord.Fields) {
        newRecord.Set(field.Name, baseRecord.Get(field.Name));
      }
      
      // Apply all overrides from the field map
      for (const field of this.compareComponent.fieldMap) {
        // Find the source record
        const sourceRecord = this.recordsToCompare.find(r => 
          r.PrimaryKey.Equals(field.CompositeKey)
        );
        
        if (sourceRecord) {
          // Set the value from the source record
          newRecord.Set(field.fieldName, sourceRecord.Get(field.fieldName));
        }
      }
      
      // Use the new record
      console.log('Composite record created:', newRecord);
      // Save the record if needed
      // await newRecord.Save();
    }
  }
}

Working with Raw Data

The component can also work with raw data objects (not BaseEntity instances). It will automatically:

  • Detect if records need additional fields from the database
  • Load missing data efficiently using RunView
  • Convert raw objects to BaseEntity instances
// You can pass raw objects with primary key values
const rawRecords = [
  { CustomerID: 1 },
  { CustomerID: 2 },
  { CustomerID: 3 }
];

// The component will automatically load full records
this.recordsToCompare = rawRecords;

API Reference

CompareRecordsComponent

Inputs

NameTypeDefaultDescription
recordsToCompareBaseEntity[][]Array of records to compare
entityNamestring''Name of the entity type being compared
visibleColumnsViewColumnInfo[][]Optional columns to display (defaults to all entity fields)
selectionModebooleanfalseWhether to enable selecting values from different records

Properties

NameTypeDescription
selectedRecordCompositeKeyCompositeKeyThe primary key of the currently selected record (in selection mode)
fieldMap{fieldName: string, CompositeKey: CompositeKey, value: any}[]Maps fields to records other than the selected record (in selection mode)
showDifferencesbooleanWhether to show only fields with different values
suppressBlankFieldsbooleanWhether to hide fields with blank values

Methods

NameReturn TypeDescription
prepareViewData()Promise<void>Refreshes the view with the current records
ResizeGrid()voidManually resize the grid

Styling

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

  • .dialog-container: Main container for the component
  • .dialog-toolbar: Contains the checkboxes for options
  • .compare-grid-rows: Applied to grid rows
  • .cell: Basic cell styling
  • .cell-not-selected: Applied to cells not selected in selection mode
  • .cell-selected: Applied to cells from the selected record in selection mode
  • .cell-selected-override: Applied to cells selected from non-selected records
  • .cell-readonly: Applied to read-only fields

Building the Package

This package uses the Angular compiler (ngc) for building:

# From the package directory
npm run build

# From the repository root using turbo
turbo build --filter="@memberjunction/ng-compare-records"

Dependencies

Peer Dependencies

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

Runtime Dependencies

  • @memberjunction/core: 2.43.0
  • @memberjunction/core-entities: 2.43.0
  • @progress/kendo-angular-grid: 16.2.0
  • tslib: ^2.3.0

Dev Dependencies

  • @angular/compiler: 18.0.2
  • @angular/compiler-cli: 18.0.2

Integration with MemberJunction

This component is designed to work seamlessly with the MemberJunction framework:

  • Entity Metadata: Uses MJ's metadata system to understand entity structure, field types, and relationships
  • Field Formatting: Leverages EntityField.FormatValue() for consistent display of values
  • Primary Key Support: Works with both single and composite primary keys using CompositeKey class
  • Dependency Detection: Uses MJ's GetRecordDependencies() to determine the default selected record
  • Data Access: Utilizes RunView for efficient batch loading of incomplete records

Advanced Features

Selection Mode Behavior

In selection mode:

  • The record with the most dependencies is automatically selected as the base record
  • Click on any cell to select that field's value from that record
  • Click on column headers to change the base record
  • Selected record header shows "✓✓✓" prefix
  • Field values from the base record have a yellowgreen background
  • Override values (from other records) have a lightpink background
  • Read-only fields cannot be selected and appear in italic

Performance Optimizations

  • Virtual Scrolling: Handles large datasets efficiently
  • Batch Loading: Loads multiple incomplete records in a single database query
  • Debounced Resizing: Window resize events are debounced to prevent excessive recalculation

Troubleshooting

Common Issues

  1. Records not displaying: Ensure entity name matches exactly (case-insensitive)
  2. Missing fields: Check that visibleColumns includes all desired fields
  3. Selection not working: Verify selectionMode is set to true
  4. Styling issues: Ensure Kendo UI theme is properly loaded in your application
2.23.2

9 months ago

2.46.0

5 months ago

2.23.1

9 months ago

2.34.0

6 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.34.2

6 months ago

2.34.1

6 months ago

2.45.0

5 months ago

2.22.1

9 months ago

2.22.0

9 months ago

2.22.2

9 months ago

2.33.0

6 months ago

2.18.3

9 months ago

2.18.1

9 months ago

2.18.2

9 months ago

2.18.0

9 months ago

2.21.0

9 months ago

2.44.0

5 months ago

2.29.0

8 months ago

2.29.2

8 months ago

2.29.1

8 months ago

2.32.0

7 months ago

2.32.2

7 months ago

2.32.1

7 months ago

2.17.0

9 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.31.0

7 months ago

2.39.0

5 months ago

2.16.1

9 months ago

2.16.0

9 months ago

2.42.1

5 months ago

2.42.0

5 months ago

2.27.1

8 months ago

2.27.0

8 months ago

2.30.0

7 months ago

2.15.2

9 months ago

2.15.1

9 months ago

2.38.0

5 months ago

2.41.0

5 months ago

2.26.1

8 months ago

2.26.0

8 months ago

2.37.1

6 months ago

2.37.0

6 months ago

2.14.0

10 months ago

2.40.0

5 months ago

2.25.0

8 months ago

2.48.0

5 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.47.0

5 months ago

2.24.1

8 months ago

2.24.0

8 months ago

2.12.0

12 months ago

2.35.1

6 months ago

2.35.0

6 months ago

2.23.0

9 months ago

2.11.0

12 months 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.7.1

1 year ago

2.6.1

1 year ago

2.6.0

1 year ago

2.5.2

1 year ago

1.6.1

1 year ago

1.6.0

1 year ago

2.4.1

1 year ago

2.4.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

2.3.0

1 year ago

2.3.2

1 year ago

2.3.1

1 year ago

2.3.3

1 year ago

1.4.1

1 year ago

1.4.0

1 year ago

2.2.1

1 year ago

2.2.0

1 year ago

1.3.3

1 year ago

1.3.2

1 year ago

1.3.1

1 year ago

1.3.0

1 year ago

2.1.2

1 year ago

2.1.1

1 year ago

2.1.4

1 year ago

2.1.3

1 year ago

2.1.5

1 year ago

2.1.0

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

2.5.0

1 year ago

2.5.1

1 year ago

1.2.2

1 year ago

1.2.1

1 year ago

1.2.0

1 year ago

1.1.1

1 year ago

1.1.0

1 year ago

1.1.3

1 year ago

1.1.2

1 year ago

1.0.11

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.8-next.6

2 years ago

1.0.8-next.5

2 years ago

1.0.8-next.4

2 years ago

1.0.8-next.3

2 years ago

1.0.8-next.2

2 years ago

1.0.8-next.1

2 years ago

1.0.8-next.0

2 years ago

1.0.7-next.0

2 years ago

1.0.8-beta.0

2 years ago

1.0.6

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago

0.9.200

2 years ago

0.9.201

2 years ago

0.9.197

2 years ago

0.9.199

2 years ago

0.9.196

2 years ago

0.9.195

2 years ago

0.9.194

2 years ago

0.9.193

2 years ago

0.9.190

2 years ago

0.9.192

2 years ago

0.9.191

2 years ago

0.9.187

2 years ago

0.9.189

2 years ago

0.9.188

2 years ago

0.9.186

2 years ago

0.9.184

2 years ago

0.9.183

2 years ago

0.9.182

2 years ago

0.9.181

2 years ago

0.9.180

2 years ago

0.9.179

2 years ago

0.9.176

2 years ago

0.9.177

2 years ago

0.9.178

2 years ago

0.9.174

2 years ago

0.9.173

2 years ago

0.9.172

2 years ago

0.9.171

2 years ago

0.9.170

2 years ago

0.9.169

2 years ago

0.9.168

2 years ago

0.9.167

2 years ago

0.9.166

2 years ago

0.9.165

2 years ago

0.9.164

2 years ago

0.9.156

2 years ago

0.9.161

2 years ago

0.9.160

2 years ago

0.9.163

2 years ago

0.9.162

2 years ago

0.9.157

2 years ago

0.9.159

2 years ago

0.9.155

2 years ago

0.9.154

2 years ago

0.9.153

2 years ago

0.9.152

2 years ago

0.9.151

2 years ago

0.9.150

2 years ago

0.9.149

2 years ago

0.9.148

2 years ago

0.9.147

2 years ago

0.9.146

2 years ago

0.9.145

2 years ago

0.9.144

2 years ago

0.9.143

2 years ago

0.9.142

2 years ago

0.9.141

2 years ago

0.9.134

2 years ago

0.9.128

2 years ago

0.9.127

2 years ago

0.9.126

2 years ago

0.9.125

2 years ago

0.9.120

2 years ago

0.9.119

2 years ago

0.9.118

2 years ago

0.9.117

2 years ago

0.9.116

2 years ago

0.9.115

2 years ago

0.9.114

2 years ago

0.9.113

2 years ago

0.9.112

2 years ago

0.9.111

2 years ago

0.9.110

2 years ago

0.9.108

2 years ago

0.9.107

2 years ago

0.9.106

2 years ago

0.9.105

2 years ago

0.9.104

2 years ago

0.9.99

2 years ago

0.9.98

2 years ago

0.9.97

2 years ago

0.9.95

2 years ago

0.9.94

2 years ago

0.9.93

2 years ago

0.9.92

2 years ago

0.9.91

2 years ago

0.9.90

2 years ago

0.9.89

2 years ago

0.9.88

2 years ago

0.9.87

2 years ago

0.9.86

2 years ago

0.9.85

2 years ago

0.9.84

2 years ago

0.9.83

2 years ago

0.9.82

2 years ago

0.9.81

2 years ago

0.9.80

2 years ago

0.9.79

2 years ago

0.9.78

2 years ago

0.9.77

2 years ago

0.9.76

2 years ago

0.9.75

2 years ago

0.9.74

2 years ago

0.9.73

2 years ago

0.9.72

2 years ago

0.9.71

2 years ago

0.9.70

2 years ago

0.9.69

2 years ago

0.9.68

2 years ago

0.9.67

2 years ago

0.9.66

2 years ago

0.9.65

2 years ago

0.9.64

2 years ago

0.9.63

2 years ago

0.9.62

2 years ago

0.9.61

2 years ago

0.9.60

2 years ago

0.9.59

2 years ago

0.9.58

2 years ago

0.9.57

2 years ago

0.9.56

2 years ago

0.9.55

2 years ago

0.9.54

2 years ago

0.9.53

2 years ago

0.9.52

2 years ago

0.9.51

2 years ago

0.9.50

2 years ago

0.9.49

2 years ago

0.9.48

2 years ago

0.9.47

2 years ago

0.9.46

2 years ago

0.9.45

2 years ago

0.9.44

2 years ago

0.9.43

2 years ago

0.9.42

2 years ago

0.9.41

2 years ago

0.9.40

2 years ago

0.9.39

2 years ago

0.9.38

2 years ago

0.9.36

2 years ago

0.9.35

2 years ago

0.9.34

2 years ago

0.9.33

2 years ago

0.9.32

2 years ago

0.9.31

2 years ago

0.9.30

2 years ago

0.9.29

2 years ago

0.9.28

2 years ago

0.9.26

2 years ago

0.9.25

2 years ago

0.9.24

2 years ago

0.9.23

2 years ago

0.9.22

2 years ago

0.9.21

2 years ago

0.9.20

2 years ago

0.9.19

2 years ago

0.9.18

2 years ago

0.9.17

2 years ago

0.9.16

2 years ago

0.9.15

2 years ago

0.9.14

2 years ago

0.9.13

2 years ago

0.9.12

2 years ago

0.9.11

2 years ago

0.9.10

2 years ago

0.9.9

2 years ago

0.9.8

2 years ago

0.9.7

2 years ago

0.9.6

2 years ago

0.9.5

2 years ago

0.9.4

2 years ago

0.9.3

2 years ago

0.9.2

2 years ago

0.9.1

2 years ago