Skip to main content

Install

Requires Angular 19 or later (signals API). Also works with Angular 20 and 21.

LogoSoupService

The Angular adapter provides an @Injectable service that wraps the core engine using Angular signals. Provide it per component instance so each <logo-soup> gets its own engine with independent state and caching.

Service API

LogoSoupService

An @Injectable that wraps the core engine. The state signal contains:

Scoping

Provide the service at the component level via providers:
This ensures each component gets an independent engine with its own image cache. If you provide it at a module or root level, all consumers share a single engine, which is usually not what you want.

Reactive Options with Signals

Since effect() automatically tracks signal reads, any input signal change re-triggers processing:
Usage in a parent template:

Dark Mode

Pass backgroundColor for proper contrast detection on opaque logos:

Loading and Error States

Read the status field from the state signal:

Visual Center Alignment

Apply visual center alignment with getVisualCenterTransform from the core package:

Computed Helpers

Use Angular’s computed() to derive values from the state signal:

Cleanup

The service uses DestroyRef.onDestroy() internally to unsubscribe from the engine and clean up blob URLs when the component is destroyed. You don’t need to handle cleanup manually.

How It Works Under the Hood

The Angular adapter bridges the core engine to Angular’s signal-based reactivity:
  • signal() holds the engine state with .asReadonly() for public access — private writable, public readonly (Angular best practice for encapsulated state)
  • engine.subscribe() pushes state changes into the Angular signal via _state.set()
  • DestroyRef.onDestroy() unsubscribes and destroys the engine when the injector is torn down — the modern Angular cleanup API (replaces OnDestroy lifecycle hook)
  • ChangeDetectionStrategy.OnPush is recommended since signals drive change detection, eliminating the need for the default strategy
  • input() / input.required() are used instead of the @Input() decorator — this is the Angular 19+ way
  • @for with track is used instead of *ngFor — Angular 19+ built-in control flow