简体   繁体   中英

How to show user position in a leaderboard with Firebase datas?

I have a leaderboard in my ionic app, where I show the position of each registered user, the usernames and the points that the users earned.

Usernames and points are stored into the database, instead, I define the position printing an index for each user for all the list that contains the users.

I want be able also to show, at the bottom of the leaderboard, the position of the logged user, like in the image:

在此处输入图片说明

in the example, if YYY it's logged I want show "USER in position 2"

How can I, with my code, retrieve user position (maybe store it in a variable) and show it on html? it is possible?

rank.ts (the function that create my leaderbord list)

   this.itemRef.orderByChild("total_points").on('value',itemSnapshot =>{
    this.items = [];
    itemSnapshot.forEach( itemSnap => {
      this.items.push(itemSnap.val());
      return false;
    });
    return this.items.reverse(); 
  });

rank.html

<ion-content padding>
<ion-card>
    <ion-card-header class ="centered" id="header_classifica" > 
        <div > USER you are in position XXX</div>
  </ion-card-header>

    <div id="table">
        <div class="row header">
            <div class="col classifica"> <b class="voci_table_header"> Posizione</b></div>
            <div class="col classifica"> <b class="voci_table_header"> Username</b></div>
            <div class="col classifica"> <b class="voci_table_header"> Punti</b></div>

        </div>

        <div class="row" *ngFor="let item of items; let i = index">
            <div class="col classifica">{{i + 1}}</div>
            <div class="col classifica">{{ item.username }} </div>
            <div class="col classifica">{{ item.total_points }} </div>
        </div>

    </div>
</ion-card>

</ion-content>

I hope that my problem it's clear. Thank you in advance.

EDIT: SOLVED PROBLEM USING THIS CODE

 this.itemRef.orderByChild("total_points").on('value',itemSnapshot =>{
      this.items = [];
      itemSnapshot.forEach( itemSnap => {
        this.items.push(itemSnap.val());
        return false;
      });
      var j = 0;
      this.items.reverse().forEach(i=>{
        j++;
        if (new String(i.username).valueOf() == new String(this.username).valueOf()){
          console.log("Trovato")
          this.position = j;
        }
      })

      return this.items; 
    });

I will give you a simple solution.

Info: The solution is working fine if you have small amount of users(200 for example) due the overhead of fetching all your users on a mobile memor y.( It will work fine with any number of users anyway but it is not required to fetch a lot of data in the mobile memory)

We will fetch all the users then we will reorder them based on their Points so our *ngFor in your template will assign the position right and we will have a variable to store the position of the current user accessing the rank page so we can bind in the selector.

1)Create a service:

First We will create a service to do so.

Info: creating a service so we can inject it in any component that need to access this sorted array and this current user.Create for example user.service.ts file . ( I think your method orderByChild can work but i didn't used before so can't tell ).

import {Injectable} from '@angular/core';
import 'rxjs/add/operator/map';
import {Http,Response} from '@angular/http';


@Injectable()
export class UserService {

sortedArray: Array <{username: string,total_points: Number}>;
currentUserPosition:Number;
    constructor(private http: Http) {

    }

getUsers(){

   let items: Array <{username: string,total_points: Number}>;

   this.itemRef.on('value',itemSnapshot =>{ // you need to define your item Ref as a global variable in this service
    itemSnapshot.forEach( itemSnap => {
      this.items.push(itemSnap.val());
    });
     this.sortUsers(items);
  });
}

sortUsers(users) {
    this.sortedArray = users.sort(function(a, b) {
       return b.total_points - a.total_points // descending
       //return a.total_points - b.total_points // accending
    });
}

getUserPosition(user){ 
    this.currentUserPosition = this.sortedArray.map(function (x) { return x.username}).indexOf(user.username);
}

}

2)Rank.ts

import {UserService} from '<path>/user.service';


constructor(public userService:UserService){
   this.userService.getUsers();
   this.userService.getUserPosition(user); // you need to pass the user accessing the rank page
}

3)Rank.html

<ion-card-header class ="centered" id="header_classifica" > 
        <div > USER you are in position {{userService.currentUserPosition + 1}}</div>
  </ion-card-header>

<div class="row" *ngFor="let item of userService.sortedArray; let i = index"> // we are accessing the sorted array defined in the service
    <div class="col classifica">{{i + 1}}</div>
    <div class="col classifica">{{ item.username }} </div>
    <div class="col classifica">{{ item.total_points }} </div>
</div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM