DEV Community

Art Stesh
Art Stesh

Posted on

Getting Started with @artstesh/postboy: Simplifying Event Management in Angular

In today's article, we will introduce the @artstesh/postboy library — a tool designed to simplify event management, improve application architecture, and make your code more modular and readable. If you're tired of overwhelming services, countless subscriptions, and tricky dependencies, @artstesh/postboy might become your go-to solution for these challenges.


Why Use @artstesh/postboy?

Modern Angular applications often face challenges such as:

  • Complexity in testing: tightly coupled services and components;
  • High coupling: components often depend heavily on each other;
  • Difficult debugging: tracking lost or broken events can be tough;
  • Adding new functionality: extending the application can lead to tangled logic.

The @artstesh/postboy library introduces an event-driven approach, making asynchronous and synchronous processes easier to manage. It focuses on clean architecture principles, isolating logic from other layers of your app. This means your project becomes more modular, your code cleaner, and your life as a developer easier.


Example of a Problem

To better understand the benefits of @artstesh/postboy, let's look at a common Angular challenge:

Problem: Using @Input for Communication Between Components

Imagine you have a parent component (ParentComponent) and two child components (ChildA and ChildB). The task is to send a variable’s state from ChildA to ChildB. The simplest (and the worst one) Angular way to handle this requires:

  1. Binding the variable in ChildA to its parent component (ParentComponent) using the @Output decorator and an event emitter.
  2. Passing the updated state from the parent to ChildB using @Input.

This approach results in tightly coupled components and a more complex flow. The communication looks like this:

ChildA --> Parent --> ChildB
Enter fullscreen mode Exit fullscreen mode

Downsides of This Approach

  1. High Coupling: Components are tightly bound through explicit @Input and @Output bindings.
  2. Difficult to Scale: Adding more components requires manual updates to bindings at multiple levels.
  3. Hard to Test: Testing the flow of data between the components requires mocking input and output connections.
  4. Unnecessary Complexity: It introduces extra boilerplate code to achieve something simple, creating dependencies on the parent component.

The Solution with @artstesh/postboy

The @artstesh/postboy library eliminates the dependency chain. Instead of having ChildA and ChildB communicate via the parent, you can send an event from ChildA that ChildB listens for directly.


Example: Solving the Problem

Step 1. Create an Event

First, define an event that will carry the state from ChildA to ChildB:

import { PostboyGenericMessage } from '@artstesh/postboy';

export class UpdateVariableEvent extends PostboyGenericMessage {
  public static readonly ID = '5861b2ea-74eb-4744-9b04-69468a278c34';

  constructor(public text: string){}
}
Enter fullscreen mode Exit fullscreen mode

Step 2. Emit the Event in ChildA

In ChildA, emit the event when the variable changes:

import {Component} from '@angular/core';
import { AppPostboyService } from './services/app-postboy.service';
import {UpdateVariableEvent} from './events/update-variable-event';

@Component({
  selector: 'app-child-a',
  template: `<input [(ngModel)]="variable" (input)="onInputChange()" />`
})
export class ChildAComponent {
  variable: string = '';

  constructor(private postboy: AppPostboyService) {
  }

  onInputChange(): void {
    postboy.fire(new UpdateVariableEvent(this.variable));
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3. Subscribe to the Event in ChildB

In ChildB, listen for the event and update the component’s state when it occurs:

import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit} from '@angular/core';
import {AppPostboyService} from './services/app-postboy.service';
import {UpdateVariableEvent} from './events/update-variable-event';

@Component({
  selector: 'app-child-b',
  template: `<p>Updated Value: {{ variable }}</p>`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildBComponent implements OnInit {
  variable: string = '';

  constructor(private postboy: AppPostboyService, private detector: ChangeDetectorRef) {
  }

  ngOnInit(): void {
    postboy.sub(UpdateVariableEvent).subscribe(ev => {
      this.variable = ev.text;
      this.detector.detectChanges();
    });
  }
}
Enter fullscreen mode Exit fullscreen mode

What Happens Behind the Scenes?

  1. When the user updates the input in ChildA, the UpdateVariableEvent is published.
  2. ChildB listens for the event and updates its variable property immediately.
  3. There’s no interaction with the parent component, keeping the flow simpler and decoupled.

Advantages of This Event-Driven Approach

  1. Decoupling

    ChildA and ChildB no longer depend directly on the parent component. Updates flow through defined events instead.

  2. Scalability

    Adding new listeners or publishers for the same event is seamless. For instance, you can add a ChildC component to listen for the UpdateVariableEvent without modifying the parent or ChildA.

  3. Simpler Code

    Instead of juggling @Input and @Output decorators with event emitters, you write clear, focused logic for publishing and subscribing to events.

  4. Improved Readability

    The code is straightforward: one part of the app publishes events, and others react to them. No need to trace convoluted binding hierarchies.

  5. Ease of Testing

    Events can be mocked and tested independently without needing to recreate the parent-child communication structure.


How to Get Started?

Visit the library's site to read more about the library. There is a simple example of installation, and using of the library in an Angular application here.


Who Can Benefit From the Library?

For Small Applications

Simplify the architecture by reducing the number of services and focusing on modular code.

For Medium and Large Applications

Manage dependencies and messaging in complex systems by dividing the app into independent zones and ensuring loose coupling between modules.


Summary

The @artstesh/postboy library offers a fresh take on event management in Angular, focusing on simplification, readability, and scalability. By switching to an event-driven approach, you get:

  • Cleaner, more modular code;
  • Testability with isolated logic;
  • Freedom from complex subscription and callback chains.

In upcoming articles, we’ll dive deeper into other powerful features of the library, such as working with asynchronous commands, locking mechanisms, and improving testing.

This library has proven its value in multiple projects within a small team of developers, and I decided to share this solution with the community. I would be delighted to receive feedback, including suggestions for extending the functionality and improving the quality of the library

Top comments (0)