Simplify Asynchronous Data Loading in Angular with ngx-data-loader
Published: 2023-04-30 19:37:30

Asynchronous data loading is a common task in Angular applications, and it often involves handling multiple complexities such as managing loading states, error handling, and switching between templates in different loading phases. Dealing with these tasks can lead to repetitive boilerplate code, making it time-consuming and prone to errors.

As an Angular developer who has faced these challenges in various projects, I decided to create [ngx-data-loader](https://www.npmjs.com/package/ngx-data-loader), an open-source package aimed at simplifying common data loading tasks in Angular applications. I'd like to highlight some of the features of the `NgxDataLoaderComponent` that could make your life easier.

## Features

### 1. Automatically Track Loading State and Remove the Need for Related *ngIf Statements

The straightforward way to load data asynchronously in Angular involves subscribing to an Observable, storing the loading state (e.g. `loading`, `loaded`, `error`, `data`) in a component variable, and using multiple `*ngIf` statements to determine when to display the data, show an error message, or indicate that the data is still loading.

Because of the relatively low complexity of having a few loading state variables and `*ngIf` statements in your templates, developers often don't take the time to implement more efficient and reusable solutions for managing asynchronous data loading, leading to repetitive code and potential inconsistencies across the application.

This is where `ngx-data-loader` comes in handy. Using `NgxDataLoaderComponent` is as simple as providing a `loadFn` and a template for your data. 

Let's look at an example in which we load an array of todos via HTTP with `ngx-data-loader`.

```html
<!-- app.component.html -->
<ngx-data-loader [loadFn]="getTodos">
  <ng-template #loading> Loading todos... </ng-template>
  <ng-template #error> Failed to load todos. </ng-template>
  <ng-template #loaded let-todos>
    <div *ngFor="let todo of todos">
      Title: {{ todo.title }} <br />
      Completed: {{ todo.completed ? 'Yes' : 'No' }}
    </div>
  </ng-template>
</ngx-data-loader>
```

```typescript
/* app.component.ts */
@Component({
  ...
})
export class AppComponent {
  getTodos = () => this.http.get('https://jsonplaceholder.typicode.com/todos');

  constructor(private http: HttpClient) {}
}
```

As you can see, there's no need for any loading state variables or `*ngIf` statements to display the appropriate template at the correct time in `AppComponent`; the `NgxDataLoaderComponent` manages the state and automatically switches between the `#loading`, `#error`, and `#loaded` templates.

### 2. Simplify Data Reloading

Setting up data reloading can often be a tedious task. With  `NgxDataLoaderComponent`, it's easy! Just call its `reload` method. 

You can do this in the template:

```html
<!-- app.component.html -->
<button (click)="loader.reload()">reload todos</button>
<ngx-data-loader [loadFn]="getTodos" #loader> ... </ngx-data-loader>
```

Or in TypeScript:

```typescript
/* app.component.ts */
@Component({
  ...
})
export class AppComponent {
  @ViewChild("loader") loader: NgxDataLoaderComponent;
  ...
  reload() {
    this.loader.reload();
  }
}
```

### 3. Reactive Parameter-Based Loading

Content can be loaded based on external variables, such as the id in your route, or a value from an input field, through the `[loadFnArgs]` input. Any time the value of the input changes, `loadFn` is called with the new arguments.

In the example below, `ngx-data-loader` fetches search results based on keywords typed in an input field:

```html
<!-- app.component.html -->
<input ngModel #searchbox />
<ngx-data-loader
  [loadFn]="searchProducts"
  [loadFnArgs]="searchbox.value"
  [debounceTime]="300"
>
  ...
</ngx-data-loader>
```

```typescript
/* app.component.ts */
@Component({
  ...
})
export class AppComponent {
  getTodos = () => this.http.get('https://jsonplaceholder.typicode.com/todos');

  constructor(private http: HttpClient) {}
}
```

And in this example, we load a todo based on the id route parameter:

```html
<!-- app.component.html -->
<ngx-data-loader [loadFn]="getTodo" [loadFnArgs]="route.params | async">
  ...
</ngx-data-loader>
```

```typescript
/* app.component.ts */
@Component({
  ...
})
export class AppComponent {
  getTodo = ({id: string}) => this.http.get(`https://jsonplaceholder.typicode.com/todos/${id}`);

  constructor(private http: HttpClient, public route: ActivatedRoute) {}
}
```

`NgxDataLoaderComponent` resets the loading state when the id route parameter changes, offering a better user experience.

## More Features

`ngx-data-loader` also offers advanced features like configurable retry and timeout, automatic cancellation of ongoing HTTP requests, and the ability to show stale data while reloading. Additionally, it provides various output events to track loading progress, such as `dataLoaded`, `loadAttemptStarted`, `loadAttemptFailed`, and `loadAttemptFinished`. You can explore these and other features in the [API documentation](https://www.npmjs.com/package/ngx-data-loader).

## Conclusion

By incorporating `ngx-data-loader` into your Angular projects, you can streamline your data loading process, improve code readability, and focus on building the core functionality of your application. Give it a try and see how it can enhance your development experience!

Don't forget to visit the [ngx-data-loader GitHub](https://github.com/rensjaspers/ngx-data-loader) repository for the latest updates, to report issues, or to contribute to the project. Happy coding!