Reputation: 1430
When i call this.getLeaderboard(); in ngOnInit() in leaderboard.component.ts the leaderboard is shown only on page start or page refresh which is normal. But i also want to fetch and show leaderboard on button click from app.component.ts.
When i click on button the flow goes to leaderboard.component which calls the leaderboard.service but nothing is shown or updated in leaderboard.component.html. If i console.log the values are there but the DOM is not updated...
What am i missing here?
app.component.html
<div class="col nopadding">
<button id="bottomButton2" type="button" class="btn btn-bottom" (click)="getLeaderboard()">
<img id="bottom2" class="navbar-bottom-pics" src="assets\img\podium.svg">
<img id="bottom22" class="navbar-bottom-pics hide" src="assets\img\podiumSelected.svg">
</button>
</div>
app.component.ts
import { Component, Injectable } from '@angular/core';
import { MatchesComponent } from './matches/matches.component';
import { LeaderboardComponent } from './leaderboard/leaderboard.component';
import { ClubStatisticsComponent } from './club-statistics/club-statistics.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [LeaderboardComponent,MatchesComponent,ClubStatisticsComponent]
})
export class AppComponent{
constructor(private match_component:MatchesComponent, private
leaderboard_component:LeaderboardComponent, private
clubstatistics_component:ClubStatisticsComponent){}
//CALLS FOR BOTTOM NAVBAR
getLeaderboard(){
//POSITION SCREEN TO TOP
window.scrollTo(0, 0);
//CALL GET LEADERBOARD
this.leaderboard_component.getLeaderboard();
}
leaderboard.component.ts
import { Component, OnInit, Injectable} from '@angular/core';
import { leaderboardInstance } from './leaderboardInstance';
import { LeaderboardService } from './leaderboard.service';
@Component({
selector: 'app-leaderboard',
templateUrl: './leaderboard.component.html',
styleUrls: ['./leaderboard.component.css'],
providers: [LeaderboardService]
})
@Injectable()
export class LeaderboardComponent implements OnInit {
public leaderboard: leaderboardInstance[];
public finalLeaderboard: leaderboardInstance[] = new Array();
constructor(private leaderboard_service: LeaderboardService) { }
ngOnInit() {
this.getLeaderboard();
}
//GET ACTUAL SERVER JSON RESPONSE AND SUBSCRIBE IT TO array
getLeaderboard(){
console.log("leaderboardComponent");
this.leaderboard_service.getLeaderboard().subscribe(leaderboard =>{ this.leaderboard = this.formatMatchesSingles(leaderboard)});
}
formatMatchesSingles(leaderboard){
console.log("formatMatches");
let uniqueNames = [];
let uniqueSurnames = [];
let matchesPlayed = [];
let matchesWon = [];
for(let i = 0; i< leaderboard.length; i++){
//FIND ALL UNIQUE NAMES
if(uniqueNames.indexOf(leaderboard[i].name1) === -1){
uniqueNames.push(leaderboard[i].name1);
}
if(uniqueNames.indexOf(leaderboard[i].name2) === -1){
uniqueNames.push(leaderboard[i].name2);
}
//FIND ALL UNIQUE SURNAMES
if(uniqueSurnames.indexOf(leaderboard[i].surname1) === -1){
uniqueSurnames.push(leaderboard[i].surname1);
}
if(uniqueSurnames.indexOf(leaderboard[i].surname2) === -1){
uniqueSurnames.push(leaderboard[i].surname2);
}
}
//CALCULATE MATCHES PLAYED
for(let i=0;i<uniqueNames.length;i++){
let played = leaderboard.reduce(function(s, o) {
if (o.name1 === uniqueNames[i] && o.doubles == "0") s++;
if (o.name2 === uniqueNames[i] && o.doubles == "0") s++;
return s;
}, 0);
matchesPlayed[i]=played;
}
//CALCULATE WINS
for(let i=0;i<uniqueNames.length;i++){
let wins = leaderboard.reduce(function(s, o) {
if (o.name1 === uniqueNames[i] && o.sets_team1 > o.sets_team2 && o.doubles == "0") s++;
else if(o.name2 === uniqueNames[i] && o.sets_team2 > o.sets_team1 && o.doubles == "0") s++;
return s;
}, 0);
matchesWon[i]=wins;
}
//CREATE USER OBJECT, ASSIGN ALL VARIABLES AND ADD IT TO ARRAY
for (let i = 0; i < uniqueNames.length; i++) {
let MatchesNo: number = parseFloat(matchesPlayed[i]);
let MatchesWonNo: number = parseFloat(matchesWon[i]);
let MatchesLostNo: number = MatchesNo - MatchesWonNo; //CALCULATE LOSES
let WinPercentage: number;
if (MatchesNo > 0 && MatchesWonNo == 0) WinPercentage = 0;
else WinPercentage = (MatchesWonNo/MatchesNo)*100; //CALCULATE PERCENTAGE
let newInstance = new leaderboardInstance();
newInstance.name = uniqueNames[i];
newInstance.surname = uniqueSurnames[i]
newInstance.played = matchesPlayed[i];
newInstance.wins = matchesWon[i];
newInstance.loses = MatchesLostNo;
newInstance.percentage = Math.floor(WinPercentage);
this.finalLeaderboard.push(newInstance);
}
//SORT
this.finalLeaderboard.sort(function(a, b){
if(a.wins === b.wins){
if(a.percentage != b.percentage){ //SORT BY PERCENTAGE
let x = a.percentage, y = b.percentage;
return y < x ? -1 : y > x ? 1 : 0;
}
else{ //IF ALSO PERCENTAGES ARE THE SAME THEN SORT BY PLAYED MATCHES
let x = a.played, y = b.played;
return y < x ? -1 : y > x ? 1 : 0;
}
}
return b.wins - a.wins //DEFAULT SORT BY WINS
});
return this.finalLeaderboard;
}
}
leaderboard.service.ts
import { Injectable } from '@angular/core';
import { leaderboardInstance } from './leaderboardInstance';
import { Observable, Subject } from 'rxjs';
import { HttpClient, HttpParams } from '@angular/common/http';
import {SHA256} from 'crypto-js';
@Injectable()
export class LeaderboardService {
constructor(private http: HttpClient) { }
getLeaderboard(): Observable<leaderboardInstance[]> {
console.log("leaderboardservice");
let url="ourAPIurl";
var salt = "1234"
var hash1 = SHA256(salt+"lalalala");
localStorage.setItem('methodName', 'GetMatchesOfGroup');
localStorage.setItem('userId', '2');
localStorage.setItem('token', String(hash1));
localStorage.setItem('id_group', '7');
localStorage.setItem('password', String(hash1));
localStorage.setItem('madCheck', 'bc8fcafb0829db3744d0aad45ebda03882d25367291de3883a8c7f75a9c45fb5');
const params = new HttpParams()
.set('methodName', localStorage.getItem('methodName'))
.set('userId', localStorage.getItem('userId'))
.set('token', localStorage.getItem('token'))
.set('id_group', localStorage.getItem('id_group'))
.set('password', localStorage.getItem('password'))
.set('madCheck', localStorage.getItem('madCheck'));
return this.http.post<leaderboardInstance[]>(url, params, {responseType: 'json'});
}
}
leaderboard.component.html
<tbody>
<tr *ngFor="let leaderboardInstance of leaderboard; index as i">
<td width=25><div id="rank1">{{i+1}}</div></td>
<td><a class="name-table">{{leaderboardInstance.name | uppercase}} {{leaderboardInstance.surname | uppercase | slice:0:1}}<span>.</span></a></td>
<td class="played">{{leaderboardInstance.played}}</td>
<td class="won">{{leaderboardInstance.wins}}</td>
<td class="loses">{{leaderboardInstance.loses}}</td>
<td class ="percentage" class="center">{{leaderboardInstance.percentage}}<span>%</span></td>
</tr>
</tbody>
</table>
</div>
Upvotes: 1
Views: 78
Reputation: 11409
Maybe the leaderboard
-array is only updating its entries, not the list itself? Angular does not detect changes if you add or remove elements from the same list. You can use the answer provided here: https://stackoverflow.com/a/42962723/1471485, or you can recreate the list when you get the leaderboard:
this.leaderboard = [].concat(this.formatMatchesSingles(leaderboard));
using [].concat
to create a new instance, and Angular will detect the change.
Upvotes: 0
Reputation: 23506
I think you want to get your component references via the ViewChild
annotation and remove them from the constructor like that:
export class AppComponent{
@ViewChild(MatchesComponent)
private match_component: MatchesComponent;
@ViewChild(LeaderboardComponent)
private leaderboard_component: LeaderboardComponent;
@ViewChild(ClubStatisticsComponent)
private clubstatistics_component: ClubStatisticsComponent;
constructor(){}
And also remove them from the providers
array in your AppComponent
. You usually only want services to be injected in the component like that.
Upvotes: 2