Core concepts

Event System

The Event System in OnboardJS allows you to react to key moments in the onboarding flow—such as step changes, flow completion, context updates, and errors. This enables you to integrate analytics, trigger side effects, or customize the onboarding experience in real time.


Overview

OnboardJS emits events during the onboarding lifecycle. You can subscribe to these events using the core engine’s API or by providing handler functions in your configuration. Events are essential for:

  • Logging and analytics
  • Custom UI updates
  • Integrating with external systems
  • Handling errors and interruptions

Available Events

The following events are emitted by the OnboardingEngine:

Event NameDescription
stateChangeEmitted whenever the engine state changes
beforeStepChangeFired before a step transition; can be cancelled or redirected
stepChangeFired after a step transition
flowCompleteEmitted when the onboarding flow is completed
stepActiveEmitted when a step becomes active
stepCompleteEmitted when a step is completed
contextUpdateEmitted when the context is updated
errorEmitted when an error occurs

Subscribing to Events

You can subscribe to events using the addEventListener method on the engine:

tsx
6 lines
1const unsubscribe = engine.addEventListener('stepChange', (event) => {
2  console.log('Step changed:', event.newStep.id);
3});
4
5// To unsubscribe:
6unsubscribe();

TypeScript Signature:

tsx
4 lines
1addEventListener(
2  event: EngineEventType,
3  listener: (event: EngineEventPayload) => void
4): UnsubscribeFunction;

Event Payloads

Each event provides a payload object with relevant data. Here are some key event payloads:

beforeStepChange

tsx
7 lines
1interface BeforeStepChangeEvent<TContext> {
2  currentStep: OnboardingStep<TContext> | null;
3  targetStepId: string | number;
4  direction: 'next' | 'previous' | 'goto' | 'skip';
5  cancel: () => void;
6  redirect: (stepId: string | number) => void;
7}
  • cancel(): Prevents the step change.
  • redirect(stepId): Redirects to a different step.

stepChange

tsx
5 lines
1interface StepChangeEvent<TContext> {
2  newStep: OnboardingStep<TContext> | null;
3  oldStep: OnboardingStep<TContext> | null;
4  context: TContext;
5}

flowComplete

tsx
3 lines
1interface FlowCompleteEvent<TContext> {
2  context: TContext;
3}

contextUpdate

tsx
4 lines
1interface ContextUpdateEvent<TContext> {
2  context: TContext;
3  previousContext: TContext;
4}

error

tsx
4 lines
1interface ErrorEvent {
2  error: Error;
3  context: any;
4}

Event Handlers in Configuration

You can also provide event handlers directly in your engine configuration:

tsx
10 lines
1const config: OnboardingEngineConfig<MyContext> = {
2  steps: [...],
3  onStepChange: (newStep, oldStep, context) => {
4    // Custom logic on step change
5  },
6  onFlowComplete: (context) => {
7    // Handle flow completion
8  },
9  // ...other handlers
10};

Supported config handlers:

  • onStepChange(newStep, oldStep, context)
  • onFlowComplete(context)
  • onStepActive(context)
  • onStepComplete(stepData, context)

These are called at the same time as the corresponding events.


Practical Examples

Logging Step Changes

tsx
6 lines
1engine.addEventListener('stepChange', (event) => {
2  analytics.track('Onboarding Step Changed', {
3    stepId: event.newStep?.id,
4    userId: event.context.currentUser?.id,
5  });
6});

Preventing Navigation

tsx
6 lines
1engine.addEventListener('beforeStepChange', (event) => {
2  if (event.targetStepId === 'dangerous-step') {
3    event.cancel();
4    alert('You cannot access this step yet.');
5  }
6});

Redirecting Navigation

tsx
5 lines
1engine.addEventListener('beforeStepChange', (event) => {
2  if (event.targetStepId === 'old-step') {
3    event.redirect('new-step');
4  }
5});

Handling Errors

tsx
4 lines
1engine.addEventListener('error', (event) => {
2  console.error('Onboarding error:', event.error);
3  // Optionally show a user-friendly message
4});

Best Practices

  • Unsubscribe from events when no longer needed to avoid memory leaks.
  • Use async handlers if you need to perform asynchronous work (e.g., API calls).
  • Avoid heavy logic in event handlers to keep onboarding responsive.
  • Leverage config handlers for common use cases; use addEventListener for advanced scenarios.

Summary

  • The event system lets you react to onboarding lifecycle events.
  • Subscribe using addEventListener or provide handlers in your config.
  • Use events for analytics, custom logic, error handling, and more.

For more, see Persistence.

Previous
Navigation & Flow