Implementing a page with Angular Pipe Async + RxJs Observable + Skeleton Loading
Tags: angular, tutorial, codenewbie
Published: 2022-10-05 20:56:32

Have you ever implemented a page with RxJs and the content is  displayed in a non-smooth way to the user!? Or when you're browsing some website and the content loads and the is jumping!?

Yes!? Perfect, because today I want to show you how we can to implement a page with the powerful Angular Pipe Async, RxJs and the beautiful power of Skeleton Loading!

So, let's start it!

___
## Creating our Product interface

First, we gonna create a simple `Product` interface to type our Observable and our API response, 
by typing our elements we get a lot of good things, like the powerful auto-complete.

The command is: `ng generate interface models/product`

```typescript
export interface Product {
  name: string;
}
```
___
## Creating our service to get our Product list

Now, let's create our Angular Service to implement the `get` method to communicate with our API and get our API Products Data. (I'm using a free mock Rest API, it is: [mockapi.io](https://mockapi.io/))

The command is: `ng generate service service/product`

```typescript
constructor(
      private _httpClient: HttpClient,
  ) { }

  getProductsList(): Observable<Product[]> {

    return this._httpClient.get<Product[]>(
        `${ environment.urlApi }/products`,
    );
  }
```
Now we have our service with our `getProductsList()` method! This method are communicating with our API and returning for us a product array Observable.
___
## Implementing the communication with our API getProucts() method!

First we need to create a Product Observable. So, in your `component.ts` file we create it, like below:

```typescript
export class MarketListComponent implements OnInit {

  productsList$: Observable<Product[]>; 

  constructor() { }

  ngOnInit(): void {
  }
}
```
> The `$` is a convention to identify an Observable variable, so if you to see a variable and the last character is a `$` probably that's an Observable.

I like to isolate my typescript code in some methods, I mean, I don't like to write my code directly in my `ngOnInit()` Lifecycle hooks. So, I'll create a simple method to isolate and call it in `ngOnInit()`! But you can write the code directly inside of `ngOnInit()`.

```typescript
export class MarketListComponent implements OnInit {

  productsList$: Observable<Product[]>; 

  constructor(
      private _moviesService: ProductsService
  ) { }

  ngOnInit(): void {
    this.getProducts();
  }

  getProducts(): void {

    this.productsList$ = this._moviesService.getProucts();
  }
}
```
What have we done!? In the constructor we declare our Products Service. And now our observable `productsList$` is receiving the `getMovies()` and getting the data from API. So, now we need to show it in our html!
___
## Implementing the template with Angular Pipe Async

When we have an Observable, we need to do the subscribe and we need to do the unsubscribe of our observable too! So, the powerful async pipe does it for us! Perfect, right!?

> In few words, the `async` pipe subscribes to an Observable and when the component is destroyed, it automatically unsubscribes!
 
Now let's implement the `async` pipe, in our html file we are do like below:

```html
<main>
  <ng-container *ngIf="(productsList$ | async) as productsList; else statusAPITemplate">
    <ng-container *ngFor="let product of productsList">
      <div class="card-product">
        <h1>
         {{ product.name }}
        </h1> 
      </div>
    </ng-container>
  </ng-container>
  <ng-template #statusAPITemplate>
    <span>
     Loading data...
    </span>
  </ng-template>
</main>
```
###Understanding the structure!

First, we have a `ng-container` with our productList$ and your `async` pipe and we declare the `productList` as our variable, that's all we need to do! Because the Angular 
`async` pipe takes care of to do subscribe and do the unsubscribe. And when the last value isn't emitted, the angular show us your `<ng-template #statusAPITemplate>` with our Loading data span! 
The second `<ng-container *ngFor="let product of productsList">` is because we have a list of products, so we need to iterate it!

And that's the result!

<img width="100%" style="width:100%" src="https://media.giphy.com/media/E045dRyUd5Moyk57u7/giphy.gif">

We have our loading template and after a seconds we have our product list content, but if you repair, the content is abruptly displayed to the user, causing a bad experience and if we have it on mobile our screen would probably jump, which is even worse.

And Voilà, we can resolve this and providing a better user experience and adding value to our page and our code, let's do it with the mighty skeleton loading!
___
## What is skeleton loading!?
> In a nutshell, skeleton loading it's an interface representation of your component is getting the data, so you simulate the space with the animated element and avoid screen-jumping, lighthouse content shift problems and get a good user experience. So, let's start!

In my Angular projects I like to use the [NGX Skeleton loader](https://github.com/willmendesneto/ngx-skeleton-loader) library, it works very well for me!

So, execute the command `npm i ngx-skeleton-loader` and import it in our component module.

Now, we need to change our Loading data span to the our new component, the `ngx-skeleton-loader`. So our code will look like below:

```html
<main>
  <ng-container *ngIf="(productsList$ | async) as productsList; else statusAPITemplate">
    <ng-container *ngFor="let product of productsList">
      <div class="card-product">
        <h1>
         {{ product.name }}
        </h1> 
      </div>
    </ng-container>
  </ng-container>
  <ng-template #statusAPITemplate>
    <!--<span>
     Loading data...
    </span>-->
      <ngx-skeleton-loader [theme]="{width: '100%', height: '95px', marginBottom: '14px', borderRadius: '1.5rem'}"
                           [count]="7">
      </ngx-skeleton-loader>
  </ng-template>
</main>
```
###Understanding the structure!
In the `theme` input we can pass CSS properties to customize our `ngx-skeleton-loader`. Then we passed some properties to look like our card-product. And in the `count` input we pass the amount of `ngx-skeleton-loader` elements we want to have.

And now, finally, we have a better user experience, we prevent a some problems with lighthouse and improve our code and our page! Take a look!

<img width="100%" style="width:100%" src="https://media.giphy.com/media/rdAIclza4VEzy2YgJQ/giphy.gif">

I really like using skeleton loading in my projects, it's powerful!

I hope you enjoyed the article and if it helped you, take a comment! and if you have any questions, leave a comment too, it will be a pleasure to talk!

See you soon guys!