Debounced
Creates a debounced signal that delays value updates until a specified time has passed without changes.
Loading demo...
Usage
Writable signal
Creates a new writable signal where both set() and update() calls are debounced:
angular-ts
import { Component, effect } from '@angular/core';
import { debounced } from '@signality/core';
@Component({
template: `
<input [(ngModel)]="value" />
`,
})
export class DebouncedInput {
readonly value = debounced('', 300);
constructor() {
effect(() => {
console.log('Debounced:', this.value());
});
}
}Computed signal
Wraps an existing signal with debounced behavior, returning a readonly signal:
angular-ts
import { Component, signal, effect } from '@angular/core';
import { debounced } from '@signality/core';
@Component({ /* ... */ })
export class DebouncedInput {
readonly rawValue = signal('');
readonly debouncedValue = debounced(this.rawValue, 300);
constructor() {
effect(() => {
console.log('Debounced:', this.debouncedValue());
});
}
}Parameters
| Parameter | Type | Description |
|---|---|---|
source | Signal<T> or T | Source signal to debounce, or initial value for writable signal |
timeMs | MaybeSignal<number> | Debounce delay in milliseconds |
options | DebouncedOptions<T> | Optional configuration (see Options below) |
Options
The DebouncedOptions<T> extends CreateSignalOptions<T> and WithInjector:
| Option | Type | Description |
|---|---|---|
equal | ValueEqualityFn<T> | Custom equality function (see more) |
debugName | string | Debug name for the signal (development only) |
injector | Injector | Optional injector for DI context |
Return Value
- When passed a signal → returns
Signal<T>(readonly) - When passed a value → returns
WritableSignal<T>
Examples
Search with API Call
angular-ts
import { Component } from '@angular/core';
import { httpResource } from '@angular/common/http';
import { debounced } from '@signality/core';
@Component({
template: `
<input
placeholder="Search..."
(input)="query.set($event.target.value)"
/>
<ul>
@if (resource.value(); as results) {
@for (result of results; track result.id) {
<li>{{ result.name }}</li>
}
}
</ul>
`,
})
export class SearchInput {
readonly query = debounced('', 400);
readonly resource = httpResource(() => `/api/search?q=${this.query()}`);
}Dynamic delay
The delay can be a signal, allowing runtime changes:
angular-ts
import { Component, computed, signal } from '@angular/core';
import { debounced } from '@signality/core';
@Component({
template: `
<input (input)="value.set($event.target.value)" />
<label>
<input
type="checkbox"
(change)="fastMode.set($any($event.target).checked)"
/>
Fast mode
</label>
`,
})
export class WithDynamicDelay {
readonly fastMode = signal(false);
readonly delay = computed(() => this.fastMode() ? 100 : 500);
readonly value = debounced('', this.delay);
}SSR Compatibility
Debounce timers are not started on the server — the initial value is returned immediately.
Type Definitions
typescript
type DebouncedOptions<T> = CreateSignalOptions<T> & WithInjector;
// Overload 1: Computed from signal (readonly)
function debounced<S extends Signal<any>>(
source: S,
timeMs: MaybeSignal<number>,
options?: DebouncedOptions<SignalValue<S>>
): Signal<SignalValue<S>>;
// Overload 2: Writable signal from value
function debounced<V>(
value: V,
timeMs: MaybeSignal<number>,
options?: DebouncedOptions<V>
): WritableSignal<V>;Related
- Throttled — Rate-limits updates instead of waiting for inactivity
- DebounceCallback — Debounced callback function