Angular
@atolljs/angular — Signal adapter for zoneless Angular. Call in an injection context (field initializer or constructor) so subscriptions release on destroy. NgModule apps get the same pools through AtollModule — the NestJS binding's forRoot/registerPool vocabulary.
Install
npm install @atolljs/core @atolljs/angularUsage
// main.ts — the connectWorker client registers as a DI provider,
// terminated on app teardown (it re-spawns lazily on the next call)
bootstrapApplication(AppComponent, {
providers: [
provideZonelessChangeDetection(),
provideAtoll({ pools: [{ name: 'counter', client: counter }] }),
],
});
// app.component.ts
import { Component, effect } from '@angular/core';
import { injectAtollPool, sharedValue, taskState } from '@atolljs/angular';
import { counterMemory } from './counter.memory';
import { counter } from './counter';
@Component({
selector: 'app-root',
template: `<button (click)="increment.run(1)">
count: {{ count() ?? '…' }}</button>`,
})
export class AppComponent {
private readonly counter = injectAtollPool<typeof counter>('counter');
count = sharedValue(counterMemory, 'count');
increment = taskState(this.counter.increment);
constructor() {
effect(() => console.log('count →', this.count()));
}
}Binding API
| Export | Signature | What it does |
|---|---|---|
provideAtoll | provideAtoll({ pools: AtollPoolDeclaration[] }, ...features) | Register worker pools or connectWorker clients ({ name, client }) as environment providers — terminated on injector destroy; also usable at route level. |
injectAtollPool | injectAtollPool<T>(name): T | Inject a pool registered by provideAtoll inside an injection context; mockable via TestBed. |
AtollModule | AtollModule.forRoot({pools?}) / forRootAsync / registerPool(decl) / registerPoolAsync | NgModule alternative to provideAtoll — same pool tokens + lifecycle, declared on the importing module; async forms resolve their factory before bootstrap. |
InjectAtollPool | @InjectAtollPool(name) | Constructor-parameter decorator form of injectAtollPool for @Injectable() classes. |
observableSignal | observableSignal(source: ObservableValue<T>): Signal<T> | Subscribe to any observable snapshot. |
sharedValue | sharedValue(memory, key, select?, options?): Signal<T | undefined> | Bind one shared-memory field to a Signal; optional selector + equality. |
taskState | taskState(task | asyncFn): { state: Signal<TaskSnapshot>, run, runOnce } | Bind an AsyncTask — or any async fn — to a Signal and get its triggers. |
Live demo
If the frame is blank, the examples aren't up — run npm run dev:all (dev servers) or npm run serve:all (built apps) from the repository root.
Notes
- Works with OnPush + zoneless change detection out of the box.
- Worker-hosted Angular trees (islands) live in the companion package @atolljs/angular-island — see the Islands page under this section.