Angular 9 and MySportsFeeds API Part 2

Sort data for ui with a custom angular pipe

This is part 2 of Angular 9 and MySportsFeeds API Part 1. We left off with a very long list of NBA players with a large player image. I would like to make the list shorter, more readable and put it in a proper order that makes sense.

Things TODO

  • Sort the order of the list

To help me sort the players by their point totals I am going to use angular cli to generate a pipe. I can add some code in the pipe that will sort my data from most points to least. Then I will add the pipe to the *ngFor directive in the html. With angular cli I can run ng g pipe orderby in the root of my angular app. I enhance the html by adding the pipe <div *ngFor="let item of nbaData | orderBy: 'nbaPts'; let i=index">. I am using the index value to show the number order in the list. The index is the number position of the item in the array.

I want to make the list shorter and only show the top 20 players. There are a few ways to do this, but I am using [ngClass] to pull this off. First I’ll create a css class .dn {display: none;} and then update the html <span [ngClass]="{'content' : i<=19, 'dn' : i>19}">. I am wrapping the player info with a <span> element. The index is binary so if the index is less than or equal to 19 apply a class name to show content and if the index is greater than 19 apply a class name that will hide the content. This will show the top 20 players and hide the rest.

It would be nice to show more players that come after the top 20. I can define some variables in the controller and use a button click event to paginate next. The default will be public page: number = 19; and public amount: number = -1; to show the top 20. I can use a button to change the values on click <button (click)="page = 19; amount = -1">1 - 20</button> &nbsp;&nbsp; <button (click)="page = 39; amount = 19">21 - 40</button>. This will allow me to toggle between 1 – 20 to 21 – 40.

//orderby.pipe.tsimport { Pipe, PipeTransform } from '@angular/core';@Pipe({name: 'orderBy', pure: false})
export class OrderBy implements PipeTransform {

transform(array: any[], field: string): any[] {
array.sort((a: any, b: any) => {
if (field === 'nbaPts') {
if (a['stats'].offense.pts >= b['stats'].offense.pts) {
return -1;
} else if (a['stats'].offense.pts <= b['stats'].offense.pts) {
return 1;
} else {
return 0;
}
}
})
}
}//app.component.ts import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpResponse, HttpHeaders, HttpRequest} from '@angular/common/http';
let headers = new HttpHeaders().set("Authorization", "Basic " + btoa(apiToken + ":" + 'MYSPORTSFEEDS'));
let url = 'https://api.mysportsfeeds.com/v2.1/pull/nba/2019-2020-regular/player_stats_totals.json?position=PG,SG,SF,PF,C';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

public nbaData: Array<any>;
public page: number = 19;
public amount: number = -1;
constructor(private http: Http) {} loadData() {
this.http.get(url, {headers})
.subscribe(res => {
console.log(res['playerStatsTotals'], 'NBA players and stats');
this.nbaData = res['playerStatsTotals'].filter(
player => player.stats != null && player.stats.gamesPlayed > 5);
});
}
ngOnInit() {
loadData();
}
}
//app.component.html<div>
<button (click)="page = 19; amount = -1">1 - 20</button> &nbsp;&nbsp; <button (click)="page = 39; amount = 19">21 - 40</button>
</div>
<div class="card" *ngIf="nbaData != null">
<h2>Points</h2>
<div *ngFor="let item of myData | orderBy: 'nbaPts'; let i=index">
<span [ngClass]="{'content' : i<=page, 'dn' : i>page || i<=amount}">
{{i + 1}}
<img src="{{item?.player?.officialImageSrc}}" alt="basketball player">
{{ item.player.firstName + ' ' + item.player.lastName}} - {{item?.player?.primaryPosition}} | #{{item.player.jerseyNumber}} {{item?.stats?.offense?.pts}} Pts
</span>
</div>
</div>
//app.component.scss
.card {
background: #444;
width: 33%;
margin: 20px;
padding: 20px;
box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12);
.dn {
display: none;
}
.content {
font-size: 16px;
img {
height: 45px;
width: 45px;
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
border: 2px solid #fff;
border-radius: 50%;
object-fit: cover;
margin-right: 3px;
}
}
}

This will give you a nice ui friendly list with some basic pagination to increase the user experience. This will lay the groundwork for listing and sorting other stats as well. Enjoy :)

Part 1: Getting Started with Angular 9 and MSF

Front-end Developer. “Lighten up Francis”