All texts goes to the top of the screen in Chat UI page


#1

i have a Chat UI page where users can text each others,but the problem is for example when user X send a text it goes to the top and when user Y reply the text should be under the text that was send by user X but no it also goes to the top above the text that was send by user X, dont know why it does that

here is my code

<StackLayout>

    <ListView height="90%" margin-bottom="50" padding="5" #list [items]="chats$ | async">

        <ng-template let-item="item">

            <GridLayout columns="*" rows="auto" class="msg">

                <StackLayout [class]="filter(item.from)" orientation="horizontal" [horizontalAlignment]="align(item.from)">

                    <Image [visibility]="showImage(item.from)" class="authorimg" stretch="aspectFill" height="30" width="30" verticalAlignment="top" src="~/images/k1.png" col="1"></Image>
                   
                    <Label [text]='item.message' class="msg_text" textWrap="true" verticalAlignment="top"></Label>
            
                </StackLayout>

            </GridLayout>

        </ng-template>

    </ListView>



    <StackLayout #chatbox height="10%">

        <GridLayout columns="*,auto" style="padding: 10">

            <TextField #textfield class="chatTextField" row="0" col="0" [(ngModel)]="message"></TextField>

            <Button #btn class="chatBtn" row="0" col="1" text="send" (tap)=chat(message)></Button>

        </GridLayout>

    </StackLayout>

</StackLayout>

chat.ts

import { Component, OnInit, AfterViewInit, ViewChild, ElementRef } from "@angular/core";
import { Observable } from 'rxjs/Observable';
import { BackendService, FirebaseService } from "../services";
import { ListView } from 'ui/list-view';
import { TextField } from 'ui/text-field';
import { ScrollView } from 'ui/scroll-view';

@Component({
    moduleId: module.id,
    selector: "chat-tab",
    templateUrl: "chat.tab.component.html",
    styleUrls: ["chat.tab.component.css"],
    
})
export class ChatTabComponent implements OnInit {

    public me: String;
    
    @ViewChild("list") lv: ElementRef;
    @ViewChild("textfield") tf: ElementRef;

    list: ListView;
    textfield: TextField;

    public constructor(
        private firebaseService: FirebaseService
    ) { }

    public chats$: Observable<any>;
    
    public ngOnInit() {
        this.me = BackendService.token;
        this.chats$ = <any>this.firebaseService.getChats();       
    }

    public ngAfterViewInit() {
        this.list = this.lv.nativeElement;
        this.textfield = this.tf.nativeElement;
    }

    scroll(count:number){
       console.log("scrolling to ", count)
       this.list.scrollToIndex(count-1);
       this.list.refresh();
    }

    chat(message: string) {
        this.firebaseService.chat(message).then((data: any) => {
            let count = this.list.items.length;
            this.scroll(count);
        });
        this.textfield.text = '';        
    }

    filter(sender) {
        if (sender == BackendService.token) {
            return "me"
        }
        else {
            return "them"
        }
    }

    align(sender) {
        if (sender == BackendService.token) {
            return "right"
           
        }
        else {
            return "left"
        }
    }
    showImage(sender) {
        if (sender == BackendService.token) {
            return "collapsed"
        }
        else {
            return "visible"
        }
    }

}

here is a screenshot

NOTE;the text “Hi” was send first then followed “Hey” then “How are you” and so on


#2

What you have inside FirebaseService, may be it’s something to do with the sort order while you are fetching data.


#3

FriebaseService

import {Injectable, NgZone} from "@angular/core";
import {User, Yowl} from "../models";
import { BackendService } from "./backend.service";
import firebase = require("nativescript-plugin-firebase");
import {Observable} from 'rxjs/Observable';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import 'rxjs/add/operator/share';

@Injectable()
export class FirebaseService {
  constructor(
    private ngZone: NgZone,
  ){}


yowls: BehaviorSubject<Array<Yowl>> = new BehaviorSubject([]);
private _allYowls: Array<Yowl> = [];
chats: BehaviorSubject<Array<Yowl>> = new BehaviorSubject([]);
private _allChats: Array<Yowl> = [];

  getMessage(){ 
    firebase.addOnMessageReceivedCallback(function (data ){
        alert(JSON.stringify(data));
    })
  }

  register(user: User) {
    return firebase.createUser({
      email: user.email,
      password: user.password
    }).then(
          function (result:any) {
            return JSON.stringify(result);
          },
          function (errorMessage:any) {
            alert(errorMessage);
          }
      )
  }

  login(user: User) {
    return firebase.login({
      type: firebase.LoginType.PASSWORD,
      passwordOptions: {
        email: user.email,
        password: user.password
      }
    }).then((result: any) => {
          BackendService.token = result.uid;
          return JSON.stringify(result);
      }, (errorMessage: any) => {
        alert(errorMessage);
      });
  }

  logout(){
    BackendService.token = "";
    firebase.logout();    
  }
  
  resetPassword(email) {
    return firebase.resetPassword({
    email: email
    }).then((result: any) => {
          alert(JSON.stringify(result));
        },
        function (errorMessage:any) {
          alert(errorMessage);
        }
    ).catch(this.handleErrors);
  }  

 getYowls(): Observable<any> {
    return new Observable((observer: any) => {
      let path = 'Yowls';
      
        let onValueEvent = (snapshot: any) => {
          this.ngZone.run(() => {
            let results = this.handleSnapshot(snapshot.value);
             observer.next(results);
          });
        };
        firebase.addValueEventListener(onValueEvent, `/${path}`);
    }).share();              
  }

  handleSnapshot(data: any) {
    //empty array, then refill and filter
    this._allYowls = [];
    if (data) {
      for (let id in data) {        
        let result = (<any>Object).assign({id: id}, data[id]);
          this._allYowls.push(result);
      }
      this.publishUpdates();
    }
    return this._allYowls;
  }

  getChats(): Observable<any> {
    return new Observable((observer: any) => {
      let path = 'Chats';
      
        let onValueEvent = (snapshot: any) => {
          this.ngZone.run(() => {
            let results = this.handleChatSnapshot(snapshot.value);
             observer.next(results);
          });
        };
        firebase.addValueEventListener(onValueEvent, `/${path}`);
    }).share();              
  }

  handleChatSnapshot(data: any) {
    //empty array, then refill and filter
    this._allChats = [];
    if (data) {
      for (let id in data) {        
        let result = (<any>Object).assign({id: id}, data[id]);
          this._allChats.push(result);
      }
      this.publishChatUpdates();
    }
    return this._allChats;
  }

  sendYowl(Yowl:any) {
    let yowl = Yowl;   
    return firebase.push(
        "/Yowls",
        { "name": "Mr. Growlllr", "username": "MrGrwwlr", "text": "Yooowwwwlll!", "UID": BackendService.token, "date": 0 - Date.now()}
      ).then(
        function (result:any) {
          return 'Yowwled!';
        },
        function (errorMessage:any) {
          console.log(errorMessage);
        }); 
  }

  chat(message:string) {
    //let chat = Chat; 
    console.log(message)  
    return firebase.push(
        "/Chats",
        { "message": message, "to": "MrGrwwlr", "from": BackendService.token, "date": 0 - Date.now()}
      ).then(
        function (result:any) {
          return "chatted";
        },
        function (errorMessage:any) {
          console.log(errorMessage);
        }); 
  }

   publishUpdates() {
    this._allYowls.sort(function(a, b) {
        if(a.date > b.date) return -1;
        if(a.date > b.date) return 1;
      return 0;
    })
    this.yowls.next([...this._allYowls]);
  }

  publishChatUpdates() {
    this._allChats.sort(function(a, b){
      if(a.date < b.date) return -1;
      if(a.date > b.date) return 1;
      return 0;
    })
    this.chats.next([...this._allChats]);
  }

  handleErrors(error) {
    console.log(JSON.stringify(error));
    return Promise.reject(error.message);
  }
}

#4

what you think is wrong with the code?


#5

As I already mentioned, it could be sorting order of your data from Firebase. If you sure your sorting order is correct, then either create a sample with Playground using simple arrays or share your repo so we may able to take a look at it.