Skip to content

@memberjunction/ng-timeline

A powerful, flexible Angular timeline component with zero external dependencies. Works with both MemberJunction BaseEntity objects and plain JavaScript objects. Pure HTML/CSS implementation with virtual scrolling, time-segment grouping, and full keyboard accessibility.

Terminal window
npm install @memberjunction/ng-timeline

The timeline renders chronologically ordered events as cards along a vertical or horizontal axis. Events can be grouped by time segments (day, week, month, quarter, year) with collapsible sections. The component uses a BeforeX/AfterX event pattern that allows container components to intercept and cancel default behaviors.

flowchart TD
    subgraph Data["Data Sources"]
        A["Plain JS Objects"]
        B["MJ BaseEntity Objects"]
    end
    subgraph Config["TimelineGroup Config"]
        C["Field Mappings"]
        D["Display Options"]
        E["Card Config"]
    end
    subgraph Component["TimelineComponent"]
        F["Time Segments"]
        G["Event Cards"]
        H["Virtual Scroll"]
        I["Keyboard Nav"]
    end

    A --> Config
    B --> Config
    Config --> Component

    style Data fill:#2d6a9f,stroke:#1a4971,color:#fff
    style Config fill:#7c5295,stroke:#563a6b,color:#fff
    style Component fill:#2d8659,stroke:#1a5c3a,color:#fff
import { TimelineModule } from '@memberjunction/ng-timeline';
@NgModule({
imports: [TimelineModule]
})
export class YourModule {}
import { TimelineGroup } from '@memberjunction/ng-timeline';
interface MyEvent {
id: string;
title: string;
eventDate: Date;
description: string;
}
const group = TimelineGroup.FromArray(myEvents, {
titleField: 'title',
dateField: 'eventDate',
descriptionField: 'description'
});
<mj-timeline [groups]="[group]"></mj-timeline>
const group = new TimelineGroup<TaskEntity>();
group.EntityName = 'Tasks';
group.DataSourceType = 'entity';
group.Filter = "Status = 'Open'";
group.TitleFieldName = 'Name';
group.DateFieldName = 'DueDate';
InputTypeDefaultDescription
groupsTimelineGroup<T>[][]Data groups to display
orientation'vertical' | 'horizontal''vertical'Timeline axis
layout'single' | 'alternating''single'Card layout
sortOrder'asc' | 'desc''desc'Event sort order
segmentGrouping'none' | 'day' | 'week' | 'month' | 'quarter' | 'year''month'Time grouping
segmentsCollapsiblebooleantrueAllow collapsing segments
enableKeyboardNavigationbooleantrueKeyboard support
virtualScrollVirtualScrollConfigVirtual scroll settings

Every user interaction emits a “before” event (cancelable) and an “after” event:

Before EventAfter EventDescription
beforeEventClickafterEventClickCard clicked
beforeEventExpandafterEventExpandCard expanded
beforeEventCollapseafterEventCollapseCard collapsed
beforeActionClickafterActionClickAction button clicked
beforeSegmentExpandafterSegmentExpandSegment expanded
beforeSegmentCollapseafterSegmentCollapseSegment collapsed
beforeLoadafterLoadData loaded
onBeforeClick(args: BeforeEventClickArgs<MyType>) {
if (args.event.entity.status === 'archived') {
args.cancel = true; // Prevent default behavior
}
}

Override card rendering with Angular templates:

<mj-timeline [groups]="groups">
<ng-template #cardTemplate let-event="event">
<div class="custom-card">{{ event.title }}</div>
</ng-template>
<ng-template #emptyTemplate>
<p>No events found.</p>
</ng-template>
</mj-timeline>

Available template refs: cardTemplate, headerTemplate, bodyTemplate, actionsTemplate, segmentHeaderTemplate, emptyTemplate, loadingTemplate

mj-timeline {
--mj-timeline-line-color: #e0e0e0;
--mj-timeline-marker-bg: #1976d2;
--mj-timeline-card-bg: #ffffff;
--mj-timeline-card-border: #e0e0e0;
--mj-timeline-text-primary: #212121;
--mj-timeline-accent: #1976d2;
--mj-timeline-card-max-width: 400px;
}
KeyAction
Arrow Down/RightNext event
Arrow Up/LeftPrevious event
Enter/SpaceToggle expand/collapse
EscapeCollapse focused event
Home/EndJump to first/last event

No external UI library dependencies. Pure Angular + HTML/CSS implementation.