ngx-data-loader
v10.0.1
Published
Lightweight Angular component to simplify asynchronous data loading.
Downloads
114
Maintainers
Readme
NgxDataLoader
Lightweight Angular component to simplify asynchronous data loading.
Demo
Installation
Install the package:
npm install ngx-data-loader
Import the module:
import { NgxDataLoaderModule } from "ngx-data-loader";
@NgModule({
imports: [
NgxDataLoaderModule,
// ...
],
// ...
})
export class AppModule {}
Usage
Basic Example
<!-- app.component.html -->
<ngx-data-loader [loadFn]="getTodos">
<ng-template #loading>Loading todos...</ng-template>
<ng-template #error let-error
>Failed to load todos. {{ error.message }}</ng-template
>
<ng-template #loaded let-todos>
@for (todo of todos; track todo.id) {
<div>
Title: {{ todo.title }}<br />
Completed: {{ todo.completed ? "Yes" : "No" }}
</div>
}
</ng-template>
</ngx-data-loader>
/* app.component.ts */
@Component({
// ...
})
export class AppComponent {
getTodos = () => this.http.get("https://jsonplaceholder.typicode.com/todos");
constructor(private http: HttpClient) {}
}
Reloading Data
<!-- app.component.html -->
<button (click)="todosLoader.reload()">Reload Todos</button>
<ngx-data-loader [loadFn]="getTodos" #todosLoader>
<!-- Loading and Error templates -->
<!-- ... -->
<ng-template #loaded let-todos>
<!-- Content here -->
<!-- ... -->
</ng-template>
</ngx-data-loader>
Loading Data Based on Route Parameters
<!-- app.component.html -->
<ngx-data-loader [loadFn]="getTodo" [loadFnArgs]="route.params | async">
<ng-template #loading>Loading todo...</ng-template>
<ng-template #error>Failed to load todo.</ng-template>
<ng-template #loaded let-todo>
Title: {{ todo.title }}<br />
Completed: {{ todo.completed ? 'Yes' : 'No' }}
</ng-template>
</ngx-data-loader>
/* app.component.ts */
@Component({
// ...
})
export class AppComponent {
getTodo = ({ id }: { id: string }) =>
this.http.get(`https://jsonplaceholder.typicode.com/todos/${id}`);
constructor(
private http: HttpClient,
public route: ActivatedRoute,
) {}
}
Loading Data Based on Search Input
⚡️ View advanced demo on StackBlitz
<!-- app.component.html -->
<h1>Search</h1>
<input ngModel #searchbox placeholder="Search" />
<ngx-data-loader
[loadFn]="searchProducts"
[loadFnArgs]="searchbox.value"
[debounceTime]="300"
>
<ng-template #loading>Searching...</ng-template>
<ng-template #error>Error</ng-template>
<ng-template #loaded let-results>
<h2>{{ results.total }} search results for "{{ searchbox.value }}"</h2>
@for (product of results.products; track product.id) {
<div>
<h3>{{ product.title }}</h3>
<p>{{ product.description }}</p>
</div>
}
</ng-template>
</ngx-data-loader>
/* app.component.ts */
@Component({
// ...
})
export class AppComponent {
searchProducts = (keywords: string) =>
this.http.get("https://dummyjson.com/products/search", {
params: { q: keywords },
});
constructor(private http: HttpClient) {}
}
Template Slots
| Name | Description | Template Context |
| ----------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| loadedTemplate
| Template shown when data has loaded (#loaded
) | $implicit: T
- the loaded dataloading: boolean
- true
if data is reloading (only if showStaleData
is true
) |
| loadingTemplate
| Template shown when data is loading (#loading
) | (none) |
| errorTemplate
| Template shown when data failed to load (#error
) | $implicit: Error
- the error objectretry: () => void
- function to retry loading data |
Properties
| Name | Description |
| ------------------------------ | -------------------------------------------------------------------------------------- |
| loadFn: () => Observable<T>
| Function that returns an Observable of the data to load. Called on init and on reload. |
| loadFnArgs?: any
| Arguments to pass to loadFn
. Changes trigger a reload. |
| initialData?: T
| Data to display on init. If set, loadFn
is not called on init. |
| debounceTime: number
| Milliseconds to debounce reloads. |
| showStaleData: boolean
| Keep displaying previous data while reloading. Default is false
. |
| loadingTemplateDelay: number
| Delay before showing the loading template (in milliseconds). Default is 0
. |
Methods
| Name | Description |
| ------------------------ | -------------------------------------------------------------- |
| reload()
| Resets the loading state and calls loadFn
. |
| cancel()
| Cancels the pending loadFn
and aborts related HTTP requests. |
| setData(data: T)
| Updates the state as if data was loaded through loadFn
. |
| setError(error: Error)
| Updates the state as if an error occurred in loadFn
. |
Events
| Name | Description |
| --------------------- | ------------------------------------------------- |
| dataLoaded
| Emits when data loads successfully. |
| loadAttemptStarted
| Emits when data loading starts. |
| loadAttemptFailed
| Emits when data fails to load. |
| loadAttemptFinished
| Emits when loading finishes (success or failure). |
| loadingStateChange
| Emits the entire loading state when it changes. |
Interfaces
interface LoadingState<T> {
loading: boolean;
loaded: boolean;
error?: Error;
data?: T;
}
FAQ
How to get type safety for the data loaded by NgxDataLoaderComponent
?
Angular doesn't currently support type inference for template variables. To get type safety, you can use a presentational component inside the #loaded
template that takes the data as a typed input.
Example:
<!-- app.component.html -->
<ngx-data-loader [loadFn]="getTodos">
<!-- ... -->
<ng-template #loaded let-todos>
<app-todo-list [todos]="todos"></app-todo-list>
</ng-template>
</ngx-data-loader>
// todo-list.component.ts
@Component({
// ...
})
export class TodoListComponent {
@Input() todos: Todo[];
}
This ensures type safety within your component's template.
If you need template type inference, consider using ngx-load-with
. Its API is similar and supports type inference.
Contributing
Please read CONTRIBUTING.md.
License
The MIT License (MIT). See License File for details.
Contact
For issues or questions, please use the GitHub issues page.