Quick Start
This guide walks you through building a profile editor component with ngx-task.
1. Create a Task
In your component, define a task using createTask(). A task wraps an asynchronous function (either returning a Promise or an Observable) and provides signal state (pending, running, result, error).
import { Component, inject } from '@angular/core';import { createTask } from 'ngx-task';import { TaskTriggerDirective, TaskDisableWhilePendingDirective } from 'ngx-task/directives';import { ProfileApiService, UserProfile } from './profile-api.service';
@Component({ selector: 'app-profile-editor', standalone: true, imports: [TaskTriggerDirective, TaskDisableWhilePendingDirective], templateUrl: './profile-editor.component.html',})export class ProfileEditorComponent { private api = inject(ProfileApiService);
userProfile: UserProfile = { name: 'Alice', email: 'alice@example.com' };
readonly saveProfile = createTask( async (profile: UserProfile, { signal }) => { // Pass the signal to fetch / HttpClient for automatic abort on cancel return this.api.updateProfile(profile, { signal }); }, { concurrency: 'drop', // Prevent duplicate submissions while active timeout: 10_000, // Abort if operation takes longer than 10s pendingDelay: 150, // Prevent visual flash for sub-150ms requests }, );}2. Bind in Template
Use Angular control flow (@if) and signals to render pending states, results, or errors:
<form (submit)="saveProfile.run(userProfile); $event.preventDefault()"> <input [(ngModel)]="userProfile.name" name="name" /> <input [(ngModel)]="userProfile.email" name="email" />
<button type="submit" [taskDisableWhilePending]="saveProfile" > @if (saveProfile.pending()) { <span class="spinner"></span> Saving... } @else { Save Changes } </button>
<button type="button" (click)="saveProfile.cancel('User clicked cancel')" [disabled]="!saveProfile.running()" > Cancel </button></form>
@if (saveProfile.result(); as updatedUser) { <p class="success">Profile saved successfully for {{ updatedUser.name }}!</p>}
@if (saveProfile.error(); as error) { <p class="error-msg">Failed to save: {{ error.message }}</p>}3. What Happens Under the Hood?
- User Clicks Save:
saveProfile.run(userProfile)triggers execution. - Anti-Flicker Delay:
pendingremainsfalsefor 150ms. If the request resolves in 50ms,pendingnever flashestrue. - Concurrency Check: Under
droppolicy, subsequent clicks while running are ignored automatically. - Lifecycle Safety: If the component is destroyed while saving,
signal.abortedflips totrueand ongoing network I/O is aborted automatically.