CHAPTER 17
The scoring component allows a person to pick a game from the schedule, update the home and away scores, and then save the updated scores back to the component. The scoring screen is shown in the following figure.

Figure 17: Scoring Screen
The user selects a game, and the screen updates both team names as labels, and the team scores as edit boxes. The user can then change the scores and click the Record Scores button to save the updated scores (and possibly update the Standings view).
Code Listing 144
/* Scoring component */ import { Component } from '@angular/core'; import { Title } from '@angular/platform-browser'; import { ViewEncapsulation } from '@angular/core'; // Our application services and interfaces import { iSchedule } from '../interfaces/schedule'; import { SoccerService} from '../services/soccerService'; @Component({ templateUrl: '../Views/scoring.html', // HTML template name styles: [` h3 {text-align:center;color:navy; font-size:x- large;margin:0px;font-weight:bold;} select { font-size:large;margin-left:25px;} `], providers: [Title,SoccerService] }) |
The scoring template is a simple HTML page where the scores can be recorded by the referee.
Code Listing 145
<h3>{{LeagueName}} </h3> <br /> <form> <p>Season starts: {{ SeasonStart }} </p> <div class="container" [ngSwitch]="CurrentRole*10"> <div *ngSwitchCase=10>Head Referee</div> <div *ngSwitchCase=20>Referee</div> <div *ngSwitchCase=30>Scorekeeper</div> <div *ngSwitchCase=40>Admin</div> <div *ngSwitchDefault>End User</div> </div> <br/> |
This code simply changes the header based on the current role, so the type of user running the page is displayed. You could use a similar approach to make certain features or options visible based on the user admin level.
Code Listing 146
<p style="font-size:large;margin-left:50px;">Game: <select (change)="onSchedChange($event.target.value)"> <option *ngFor="let currentRow of MySchedule" value={{currentRow.id}}> {{ currentRow.HomeTeam +" vs "+ currentRow.AwayTeam }} </option> </select> </p> |
This code uses the *ngFor directive to populate the drop-down box by iterating over an array. It also binds the change event of the select element to an event inside the class code.
Code Listing 147
<div class="row"> <div class="col-md-2"> </div> <div class="form-group col-md-3"> <label for="HomeTeam" style="float:left;font-size:large;">{{HomeTeam}}</label> </div> <div class="form-group col-md-2"> <input type="number" style="width:80px;float:right;text-align:right;" [(ngModel)]="HomeScore" name="HomeScoreVal" class="form-control" /> </div> </div> <div class="row"> <div class="col-md-2"> </div> <div class="form-group col-md-3"> <label for="AwayTeam" style="float:left;font-size:large;">{{AwayTeam}}</label> </div> <div class="form-group col-md-2"> <input type="number" style="width:80px;float:right;text-align:right;" [(ngModel)]="AwayScore" name="AwayScoreVal" class="form-control" /> </div> </div> <br/> |
We then have code to display the home and away team names using interpolation and property binding. This links the edit box value with the variable in the component.
Our final part of the template links the button click event to a method (which must be public) inside the component.
Code Listing 148
<button type="button" (click)="onRecordScores()" style="font-size:large;margin-left:50px;"> Record Scores </button> </form> |
There are several data-binding elements within the HTML template to collect data and trigger events within the component code. The (click) binding will call the onRecordScores() method inside the component.
You will also notice some simple interpolations, such as HomeTeam and AwayTeam, for displaying the selected team names as part of the screen display.
The class code for the scoring component performs several actions: it populates the schedule array, detects when a user changes the drop-down box, and fills the score based on the schedule information. It also has code to handle the record scores option when the user clicks the button.
We declare several variables inside the component that we will use both for the component itself and public variables for the template page.
Code Listing 149
private UsingAsync: boolean = false; private CurGame: number = 0; public MySchedule: iSchedule[]; public LeagueName: string; public HomeTeam : string; public AwayTeam : string; public HomeScore : number = 0; public AwayScore : number = 0; public SeasonStart: Date = new Date; public CurrentRole: number = 1; |
The constructor code updates some variables and specifies the service to be used throughout the component.
Code Listing 150
public constructor(private _soccerService: SoccerService ) { this.LeagueName = "Over 30 men's league"; this.getSchedule(); this.SeasonStart.setTime( this.SeasonStart.getTime() +4 * 86400000 ); if (this.MySchedule.length>0) { this.UpdVariables(0); // Default to first game this.CurGame = 1; } } |
Any method that the template code references must be declared as public. We need two public methods: one for the select box change, and another for the user clicking the button to record the scores.
Code Listing 151
public onSchedChange(GameValue:number) { if (GameValue>0) { this.UpdVariables(GameValue); this.CurGame = GameValue; } } // Get the score from the form and update it public onRecordScores() { this.MySchedule[this.CurGame-1].AwayScore = Number(this.AwayScore); this.MySchedule[this.CurGame-1].HomeScore = Number(this.HomeScore); } |
The private methods are generally methods needed to support the component, but do not need to be used outside the component body. We have a couple private methods in this component.
Code Listing 152
// Update screen variable based on current game private UpdVariables(GameID: number) { // Need to search Schedule array, looking for game ID var x : number = 0; if (GameID >0) { x = GameID-1; } this.HomeTeam = this.MySchedule[x].HomeTeam; this.AwayTeam = this.MySchedule[x].AwayTeam; this.HomeScore = this.MySchedule[x].HomeScore; this.AwayScore = this.MySchedule[x].AwayScore; } // Get the schedule (only showing games not yet scored) private getSchedule() { if (this.UsingAsync) { let xx = this._soccerService.getScheduleAsync(); xx.then((Schedules:iSchedule[])=> this.MySchedule =Schedules ); } else { this.MySchedule = this._soccerService.getSchedule(); } } |
If you update the scores, and then go back to the Standings page, you will see the changes reflected in the standings, goals for, and goals against. For an actual application, you would most likely write a web service and use the HTTP module to persist the changes to the back-end database.
In this chapter, we looked at a simple example of getting data back and forth from the form to the component, and responding to form events and button clicks.