npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@memberjunction/ng-explorer-core

v2.125.0

Published

MemberJunction Explorer: Core Angular Components

Readme

@memberjunction/ng-explorer-core

The @memberjunction/ng-explorer-core package provides the core components and infrastructure for the MemberJunction Explorer application. It serves as the foundation for building a complete data exploration and management interface based on MemberJunction entities.

Overview

Explorer Core is a comprehensive Angular library that implements the MemberJunction Explorer application's core functionality. It provides a dynamic resource-based architecture for managing entities, records, reports, dashboards, queries, and other data resources within the MemberJunction ecosystem.

Features

  • Dynamic Resource Container Architecture: Loads components at runtime based on resource type
  • Complete Navigation System: Drawer-based navigation with workspace and tab management
  • Entity Management: Browse, view, create, edit, and delete entity records
  • Dashboard System: Create, edit, and view interactive dashboards
  • Report Integration: Display and manage reports
  • Query Support: Execute and display query results
  • Search Integration: Unified search results display
  • User Views: Support for custom user-defined views
  • Authentication: Built-in authentication components and guards
  • Responsive Design: Mobile-friendly UI that adapts to different screen sizes
  • Workspace Management: Persistent workspace with saved tabs and state
  • Event-Driven Architecture: Comprehensive event system for component communication

Installation

npm install @memberjunction/ng-explorer-core

Requirements

  • Angular 18.0.2 or higher
  • MemberJunction core libraries:
    • @memberjunction/core v2.43.0+
    • @memberjunction/core-entities v2.43.0+
    • @memberjunction/global v2.43.0+
  • Kendo UI for Angular v16.2.0+
  • TypeScript 4.9+

Basic Setup

Module Import

Import the ExplorerCoreModule in your application module:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ExplorerCoreModule } from '@memberjunction/ng-explorer-core';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    ExplorerCoreModule
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Routing Configuration

The Explorer Core module includes its own routing configuration. You can integrate it with your application's routing:

import { Routes } from '@angular/router';
import { AuthGuardService } from '@memberjunction/ng-explorer-core';

const routes: Routes = [
  {
    path: '',
    canActivate: [AuthGuardService],
    loadChildren: () => import('@memberjunction/ng-explorer-core').then(m => m.ExplorerCoreModule)
  }
];

Core Components

Resource Container Component

The heart of the Explorer architecture, dynamically loading components based on resource type:

import { Component } from '@angular/core';
import { ResourceData } from '@memberjunction/core-entities';

@Component({
  template: `
    <mj-resource
      [Data]="resourceData"
      [isVisible]="isActive"
      (ResourceRecordSaved)="onResourceSaved($event)"
      (ContentLoadingStarted)="onLoadingStarted($event)"
      (ContentLoadingComplete)="onLoadingComplete($event)">
    </mj-resource>
  `
})
export class MyComponent {
  resourceData: ResourceData = {
    ID: 'unique-id',
    Name: 'My Resource',
    ResourceType: 'Records',
    ResourceRecordID: '123',
    Configuration: {
      Entity: 'Contacts'
    }
  };
  
  isActive = true;
  
  onResourceSaved(entity: BaseEntity) {
    console.log('Resource saved:', entity);
  }
  
  onLoadingStarted(container: ResourceContainerComponent) {
    console.log('Loading started');
  }
  
  onLoadingComplete(container: ResourceContainerComponent) {
    console.log('Loading complete');
  }
}

Navigation Component

Provides the main application navigation with workspace and tab management:

@Component({
  template: `
    <mj-navigation 
      [applicationName]="'My Application'">
    </mj-navigation>
  `
})
export class AppComponent { }

Home Component

Displays navigation items configured to show on the home screen:

@Component({
  template: `<mj-home></mj-home>`
})
export class HomePageComponent { }

Entity Management Components

Entity Browser

@Component({
  template: `
    <mj-single-entity 
      [entityName]="'Contacts'"
      [viewID]="viewId">
    </mj-single-entity>
  `
})
export class EntityBrowserComponent {
  viewId?: string; // Optional view ID
}

Record Editor

@Component({
  template: `
    <mj-single-record 
      [entityName]="'Contacts'"
      [PrimaryKey]="recordKey"
      [newRecordValues]="defaultValues"
      (recordSaved)="onRecordSaved($event)"
      (loadComplete)="onLoadComplete()">
    </mj-single-record>
  `
})
export class RecordEditorComponent {
  recordKey = new CompositeKey([{ FieldName: 'ID', Value: '123' }]);
  defaultValues = { CompanyID: 1 }; // For new records
  
  onRecordSaved(entity: BaseEntity) {
    console.log('Record saved:', entity);
  }
  
  onLoadComplete() {
    console.log('Record loaded');
  }
}

Dashboard Components

@Component({
  template: `
    <mj-single-dashboard 
      [dashboardId]="dashboardId"
      [editMode]="false">
    </mj-single-dashboard>
  `
})
export class DashboardViewerComponent {
  dashboardId = '456';
}

Form Toolbar

Provides consistent form actions across the application:

@Component({
  template: `
    <mj-form-toolbar
      [record]="entity"
      [EditMode]="true"
      (SaveRecord)="save()"
      (DeleteRecord)="delete()"
      (CancelEdit)="cancel()">
    </mj-form-toolbar>
  `
})
export class FormComponent {
  entity: BaseEntity;
  
  save() { /* Save logic */ }
  delete() { /* Delete logic */ }
  cancel() { /* Cancel logic */ }
}

Resource Types and Wrappers

The Explorer supports multiple resource types through specialized wrapper components:

Creating Custom Resource Types

import { Component } from '@angular/core';
import { RegisterClass } from '@memberjunction/global';
import { BaseResourceComponent } from '@memberjunction/ng-shared';

@RegisterClass(BaseResourceComponent, 'CustomResource')
@Component({
  selector: 'mj-custom-resource',
  template: `
    <div class="custom-resource">
      <h2>{{ Data.Name }}</h2>
      <!-- Custom resource implementation -->
    </div>
  `
})
export class CustomResource extends BaseResourceComponent {
  async GetResourceDisplayName(data: ResourceData): Promise<string> {
    return `Custom: ${data.Name}`;
  }
  
  async GetResourceIconClass(data: ResourceData): Promise<string> {
    return 'fa-solid fa-star';
  }
}

Built-in Resource Types

  • Records: Entity record viewing and editing
  • Reports: Report display and execution
  • Dashboards: Interactive dashboard display
  • Queries: Query execution and results
  • UserViews: Custom user-defined views
  • SearchResults: Unified search results
  • ListDetail: Master-detail layouts

Event System

The Explorer uses a comprehensive event system for component communication:

import { MJGlobal, MJEventType } from '@memberjunction/global';
import { EventCodes } from '@memberjunction/ng-shared';

// Subscribe to events
const subscription = MJGlobal.Instance.GetEventListener(false)
  .subscribe((event) => {
    if (event.eventCode === EventCodes.ComponentEvent) {
      console.log('Component event:', event.args);
    }
  });

// Emit events
MJGlobal.Instance.RaiseEvent({
  eventCode: EventCodes.ComponentEvent,
  eventType: MJEventType.ComponentEvent,
  sourceComponent: this,
  args: { action: 'save', entityName: 'Contacts' }
});

Authentication and Guards

Auth Guard Service

import { Routes } from '@angular/router';
import { AuthGuardService } from '@memberjunction/ng-explorer-core';

const routes: Routes = [
  {
    path: 'secure',
    canActivate: [AuthGuardService],
    component: SecureComponent
  }
];

Entities Guard

import { EntitiesGuard } from '@memberjunction/ng-explorer-core';

const routes: Routes = [
  {
    path: 'entities/:entityName',
    canActivate: [EntitiesGuard],
    component: EntityComponent
  }
];

Advanced Features

Workspace Management

The Explorer automatically manages workspace state, including:

  • Open tabs and their state
  • Navigation history
  • User preferences
  • Resource configurations

Tab Management

// Access tab management through the navigation component
@ViewChild(NavigationComponent) navigation: NavigationComponent;

// Open a new tab
this.navigation.openTab({
  label: 'New Contact',
  icon: 'fa-user',
  data: {
    resourceType: 'Records',
    entityName: 'Contacts',
    recordId: 'new'
  }
});

Custom Expansion Panels

@Component({
  template: `
    <mj-expansion-panel
      [title]="'Advanced Options'"
      [expanded]="false"
      (expandedChange)="onExpandedChange($event)">
      <!-- Panel content -->
    </mj-expansion-panel>
  `
})
export class MyPanelComponent { }

Build Scripts

{
  "scripts": {
    "build": "ngc",
    "watch": "ngc -w",
    "test": "echo \"Error: no test specified\" && exit 1"
  }
}

Development

Building the Package

# Build the package
npm run build

# Watch mode for development
npm run watch

Package Structure

explorer-core/
├── src/
│   ├── lib/
│   │   ├── auth-button/
│   │   ├── dashboard-browser-component/
│   │   ├── generic/
│   │   ├── guards/
│   │   ├── header/
│   │   ├── home-component/
│   │   ├── navigation/
│   │   ├── resource-wrappers/
│   │   ├── single-dashboard/
│   │   ├── single-entity/
│   │   ├── single-record/
│   │   └── ...
│   ├── generic/
│   ├── shared/
│   ├── module.ts
│   └── public-api.ts
├── package.json
└── tsconfig.json

Integration with Other MJ Packages

The Explorer Core integrates seamlessly with:

  • @memberjunction/ng-auth-services: Authentication and authorization
  • @memberjunction/ng-container-directives: Layout management
  • @memberjunction/ng-entity-permissions: Entity-level permissions
  • @memberjunction/ng-file-storage: File upload and management
  • @memberjunction/ng-record-changes: Audit trail functionality
  • @memberjunction/ng-user-view-grid: Data grid components
  • @memberjunction/ng-dashboards: Dashboard creation and management
  • @memberjunction/ng-resource-permissions: Resource-level permissions

Best Practices

  1. Resource Loading: Always check isVisible before loading heavy resources
  2. Event Handling: Unsubscribe from events in ngOnDestroy
  3. Tab Management: Limit concurrent tabs to maintain performance
  4. Entity Access: Use metadata to check entity permissions before operations
  5. Error Handling: Implement proper error handling for all async operations

Troubleshooting

Common Issues

  1. Resource not loading: Ensure the resource type is properly registered
  2. Navigation errors: Check route configuration and guards
  3. Missing icons: Verify Font Awesome is properly loaded
  4. Performance issues: Review tab count and resource loading strategies

License

ISC License - see LICENSE file for details