
Security News
Happy Birthday, Shai-Hulud
It has been one year since Shai-Hulud made its first appearance on npm.
@mj-biz-apps/common-ng
Advanced tools
BizApps Common Angular bootstrap - form components and module for the Common business entities Open App
Angular bootstrap and reusable UI component library for the BizApps Common MemberJunction Open App. Provides form components, data widgets, and composed detail views for People, Organizations, and their related data (addresses, contact methods, relationships).
npm install @mj-biz-apps/common-ng
Peer dependencies: @angular/core >=21, @angular/common >=21
Import and call the bootstrap function during application initialization to register all entity classes and form components with MemberJunction's class factory:
import { LoadBizAppsCommonClient } from '@mj-biz-apps/common-ng';
// Call during app bootstrap (e.g., in APP_INITIALIZER or main.ts)
LoadBizAppsCommonClient();
For NgModule-based applications, import the form modules:
import { GeneratedFormsModule, CustomFormsModule } from '@mj-biz-apps/common-ng';
@NgModule({
imports: [GeneratedFormsModule, CustomFormsModule]
})
export class AppModule {}
LoadBizAppsCommonClient() also registers three BaseResourceComponent drivers so MJ Explorer can mount the Common application:
CommonDirectoryResource — operational dashboard (counts, gap queues, recent people)CommonPeopleResource — searchable people listCommonOrganizationsResource — searchable organization listSee the root README and docs/angular-components.md for the information architecture.
The package follows a three-tier component architecture:
Form Components (NgModule-declared, @RegisterClass)
└── Composed Detail Views (standalone)
└── Atomic Widgets (standalone)
@RegisterClass. They wrap a composed detail view inside mj-record-form-container to get the standard MJ form chrome (save/delete toolbar, navigation, favorites, history).| Component | Selector | Description |
|---|---|---|
PersonHeaderComponent | <bizapps-person-header> | Dark gradient header with avatar initials, name, job title, and organization navigation link. Edit mode stacks identity fields as labeled columns (wrap each mj-form-field); two-across only at ≥52rem |
PersonSummaryCardsComponent | <bizapps-person-summary-cards> | Four metric cards showing email, phone, address count, and relationship count (lazy-loaded) |
PersonIdentitySectionComponent | <bizapps-person-identity-section> | Section card with identity fields: name, preferred name, prefix/suffix/gender, date of birth |
PersonProfessionalSectionComponent | <bizapps-person-professional-section> | Section card with professional fields: title, job title, organization link, email, phone, bio |
PersonAccountSectionComponent | <bizapps-person-account-section> | Section card with account fields: linked user and status |
| Component | Selector | Description |
|---|---|---|
OrgHeaderComponent | <bizapps-org-header> | Top bar with logo initial, name, type badge, status, founded year, and website action. Same edit-mode field wrapping and stacked / two-across layout as the Person header |
OrgIdentitySectionComponent | <bizapps-org-identity-section> | Panel card with all organization detail fields: name, legal name, type, status, contacts, parent, description |
OrgHierarchyTreeComponent | <bizapps-org-hierarchy-tree> | Self-loading tree view showing parent, current, and child organizations with navigation |
| Component | Selector | Description |
|---|---|---|
AddressEditorComponent | <bizapps-address-editor> | Full CRUD for addresses via the AddressLink polymorphic pattern. Compact table layout with inline editing, primary badge, and type management |
ContactMethodListComponent | <bizapps-contact-method-list> | Full CRUD for contact methods (email, phone, social, etc.) with icon-coded types, copy-to-clipboard, and primary designation |
RelationshipListComponent | <bizapps-relationship-list> | Grouped relationship viewer organized by category (Employment, Personal, Business) with directional label logic and navigation events |
| Component | Selector | Description |
|---|---|---|
PersonDetailComponent | <bizapps-person-detail> | Command Center layout — dark header, summary cards, two-column body with all person sections and CRUD widgets |
OrgDetailComponent | <bizapps-org-detail> | HQ View layout — dark icon sidebar, header bar, two-column body with identity, hierarchy tree, and CRUD widgets |
| Component | Selector | Registered Entity |
|---|---|---|
BizAppsPersonFormComponent | <bizapps-person-form> | MJ.BizApps.Common: People |
BizAppsOrganizationFormComponent | <bizapps-organization-form> | MJ.BizApps.Common: Organizations |
All atomic widgets and composed detail views are standalone components that can be imported directly into any Angular component or module:
<!-- Person Command Center (all-in-one) -->
<bizapps-person-detail
[Record]="personEntity"
[EditMode]="isEditing"
[FormContext]="formContext"
(Navigate)="onNavigate($event)">
</bizapps-person-detail>
<!-- Organization HQ View (all-in-one) -->
<bizapps-org-detail
[Record]="orgEntity"
[EditMode]="isEditing"
[FormContext]="formContext"
(Navigate)="onNavigate($event)">
</bizapps-org-detail>
Use atomic widgets independently when you only need part of the layout:
<!-- Address editor for any entity that supports the AddressLink pattern -->
<bizapps-address-editor
EntityName="MJ.BizApps.Common: People"
[RecordID]="personId">
</bizapps-address-editor>
<!-- Contact methods for a person -->
<bizapps-contact-method-list
[PersonID]="personId">
</bizapps-contact-method-list>
<!-- Contact methods for an organization -->
<bizapps-contact-method-list
[OrganizationID]="orgId">
</bizapps-contact-method-list>
<!-- Relationships for a person -->
<bizapps-relationship-list
[PersonID]="personId"
(Navigate)="onNavigate($event)">
</bizapps-relationship-list>
<!-- Organization hierarchy tree (self-loading) -->
<bizapps-org-hierarchy-tree
[OrganizationID]="orgId"
(Navigate)="onNavigate($event)">
</bizapps-org-hierarchy-tree>
<!-- Person header only -->
<bizapps-person-header
[Record]="personEntity"
(Navigate)="onNavigate($event)">
</bizapps-person-header>
| Input | Type | Default | Description |
|---|---|---|---|
Record | Entity object | undefined | The MJ entity record to display |
EditMode | boolean | false | Whether fields are editable or read-only |
FormContext | FormContext | undefined | Shared form state (validation, visibility settings) |
| Output | Type | Description |
|---|---|---|
Navigate | EventEmitter<FormNavigationEvent> | Emitted when a navigation link is clicked (org link, relationship target, hierarchy node). The parent handles actual routing. |
| Input | Type | Description |
|---|---|---|
EntityName | string | MJ entity name (e.g. 'MJ.BizApps.Common: People') |
RecordID | string | ID of the parent record |
| Input | Type | Description |
|---|---|---|
PersonID | string | null | Person record ID (set one) |
OrganizationID | string | null | Organization record ID (set one) |
| Input | Type | Description |
|---|---|---|
PersonID | string | null | Person record ID (set one) |
OrganizationID | string | null | Organization record ID (set one) |
| Input | Type | Description |
|---|---|---|
OrganizationID | string | null | Organization ID to build the tree around |
| Output | Type | Description |
|---|---|---|
Navigate | EventEmitter<FormNavigationEvent> | Parent org navigation |
WebsiteClick | EventEmitter<string> | Emitted with the website URL when the button is clicked |
All components use MemberJunction's RunView / RunViews for data access:
Address + AddressLink entities. Batch-loads addresses, types, and links.ContactMethod entity, with ContactType lookup for icons.Relationship entities with directional label logic (ForwardLabel/ReverseLabel) and groups by RelationshipType.Category.RunViews call.RunViews with ResultType: 'simple'.The package re-exports everything needed for consumption:
// Bootstrap
export { LoadBizAppsCommonClient } from '@mj-biz-apps/common-ng';
export { CLASS_REGISTRATIONS } from '@mj-biz-apps/common-ng';
// Modules
export { GeneratedFormsModule } from '@mj-biz-apps/common-ng';
export { CustomFormsModule } from '@mj-biz-apps/common-ng';
// All 13 standalone components
export { PersonHeaderComponent } from '@mj-biz-apps/common-ng';
export { PersonSummaryCardsComponent } from '@mj-biz-apps/common-ng';
export { PersonIdentitySectionComponent } from '@mj-biz-apps/common-ng';
export { PersonProfessionalSectionComponent } from '@mj-biz-apps/common-ng';
export { PersonAccountSectionComponent } from '@mj-biz-apps/common-ng';
export { PersonDetailComponent } from '@mj-biz-apps/common-ng';
export { OrgHeaderComponent } from '@mj-biz-apps/common-ng';
export { OrgIdentitySectionComponent } from '@mj-biz-apps/common-ng';
export { OrgHierarchyTreeComponent, OrgTreeNode } from '@mj-biz-apps/common-ng';
export { OrgDetailComponent } from '@mj-biz-apps/common-ng';
export { AddressEditorComponent } from '@mj-biz-apps/common-ng';
export { ContactMethodListComponent } from '@mj-biz-apps/common-ng';
export { RelationshipListComponent } from '@mj-biz-apps/common-ng';
cd packages/Angular
npm run build # Runs ngc (Angular compiler)
The output is written to dist/ and consumed via the main and types fields in package.json.
@RegisterClass(BaseFormComponent, ...) pattern expects components to be declared in a module for the class factory to resolve them.@if/@for block syntax used throughout (Angular 21 modern template syntax).inject() function used for DI instead of constructor injection.FAQs
BizApps Common Angular bootstrap - form components and module for the Common business entities Open App
We found that @mj-biz-apps/common-ng demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 10 open source maintainers collaborating on the project.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.

Security News
GitHub Actions now supports cache-mode, a least-privilege control on the Actions cache aimed at the cache poisoning technique behind recent compromises.