How to show comment replies in descending order based on time

Unfortunately this is the Third Forum I am requesting the suggestion.

Question in short:

What is the best way to show comments in ionic2, especially when it has replies. I need to show replies based on their time.

++++++++++++++++++++++++++++++

Question in detail:

I have the below data with me in json format.

This is the list of comments. In this example 19 comments are there under items tag.

http://www.jsoneditoronline.org/?id=47b282c498505ed25869dc36f5f3bd58

Comments are already sorted based on Date published.

Now on the Item Id 10th there are two replies to this comment.

I am looking for a way to order this reply based on publishedAt time.

Below is my html: Here videoComments = the json data specified above

I tried using angualr-pipes orderBy pipe but that did not work for me, is there any alternative way?

<ion-list>
  <ion-item *ngFor="let comment of videoComments">
    <!-- here i Print the details what is required , next if there are any reply i would like to show them-->   
    <div *ngIf="comment.snippet.totalReplyCount != 0">
      <ion-list>
        <ion-item *ngFor="let reply of comment.replies.comments | orderBy: 'publishedAt'"> 
          <!-- Above orderBy pipe is not working , may be my syntax is wrong -->
           <!-- I would like to show replies in ascending order of when it was submitted-->
          <!-- Details of replies will be shown here -->          
        </ion-item>
      </ion-list>
    </div>
  </ion-item>
</ion-list>

I’d sort them in your page class myself.

Something along the lines of:

this.videoComments.forEach(comment => {
    comment.replies.comments = comment.replies.comments.sort((a, b) => new Date(b.publishedAt) - new Date(a.publishedAt));
});

I agree. Don’t sort in your template. It will kill the performance of your page.

I’m using moment.js, you could just stick to the Date class.

import { Pipe, PipeTransform } from '@angular/core';

import moment from 'moment';

@Pipe({
  name: 'sortByDatetime',
})
export class SortByDatetime implements PipeTransform {

  transform(value: any, keyName?: string): Object[] {

    value.sort((a: Object, b: Object): number => {
      var first = moment(a[keyName], 'YYYY-MM-DD HH:mm:ss');
      var second = moment(b[keyName], 'YYYY-MM-DD HH:mm:ss');
      // console.log('SortBy: Compare ' + first.format('YYYY-MM-DD HH:mm:ss') + ' to ' + second.format('YYYY-MM-DD HH:mm:ss'));
      return first.isBefore(second) ? -1 : first.isAfter(second) ? 1 : 0;
    });
    return value;
  }
}

Call it using

<ion-item *ngFor='let reply of comment.replies.comments | sortByDatetime:"publishedAt"'>

@SigmundFroyd Thank you for your response.

I apologise for my limited knowledge here. Below is my Typescript , where I should be adding your piece of code?

Also will your snippet manage more than 2 replies?

  constructor(public navCtrl: NavController, public params: NavParams,public ytapi3 : YouTubeApi3) {
    this.videoId = params.data;
    this.ytapi3
      .getLatestComments(this.videoId)
      .subscribe((data : any) => {
        this.videoComments = data.items;   
        console.log(this.videoComments)
       }) 

  }

Thank you very much

@elvis_gn Thank you for your help here. I will wait for the solution which I can apply on my component. If I fail then I will go with your option.

You would basically update your constructor to look like this:

constructor(public navCtrl: NavController, public params: NavParams,public ytapi3 : YouTubeApi3) {
   this.videoId = params.data;
   this.ytapi3
   .getLatestComments(this.videoId)
   .subscribe((data : any) => {
      this.videoComments = data.items;
      this.videoComments.forEach(comment => {
         comment.replies.comments = comment.replies.comments.sort((a, b) => new Date(b.publishedAt) - new Date(a.publishedAt));
      });

      console.log(this.videoComments)
   });
}

This will indeed support any number of replies and comments.

The code I provided will work on html, on any array element looped in the ngFor. Number of array elements will not matter.

If you want to do it in the component, then simply create the ‘transform’ function and call it with the array as value and keyName as the publishedAt.

@elvis_gn I am sure what you are suggesting to do in component might be an easy task for an experienced person.
I am still learning. Is it possible to provide little more information or using my existing Component code is it possible to alter it and show how this can be achieved?
Transform Function do you have any sample code where I can look up?

@SigmundFroyd

Thanks a lot for your assistance. I really appreciate this.

I changed as suggested, Even after that error did not go so I changed this assignment on my component
videoComments: Array <object>;
to
videoComments: any;

this removed the error Property 'replies' does not exist on type 'Object'.

But getting a new error:
The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
The right-hand side of an arithmetic operation must be of type ‘any’, ‘number’ or an enum type.

Ah, my apologies. Probably. I forgot about that aspect.

All you should have to do add a existence check:

this.videoComments.forEach(comment => {
   if(!!comment.replies) {
         comment.replies.comments = comment.replies.comments.sort((a, b) => new Date(b.publishedAt) - new Date(a.publishedAt));
      });
   }

(Sorry for the formatting. I’m on my phone at the moment)

I just updated my above comment.

I get this error now

The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type

I feel like we are almost there but yet not reached the goal. I have been struggling with this from almost 3 weeks now :frowning:

D’oh. I managed to put the end brackets in the wrong position.

this.videoComments.forEach(comment => {
   if(!!comment.replies) {
         comment.replies.comments = comment.replies.comments.sort((a, b) => new Date(b.publishedAt) - new Date(a.publishedAt));
   }
});

@SigmundFroyd is there any difference between your last two replies? I see the code is same :confused:

Ok I observed the difference. But still no luck.

Not sure will this have any impact, my publishedAt value is like this"2017-06-30T10:00:40.000Z"

@SigmundFroyd thanks a lot for your help.
Finally it looks like I sorted this issue.

two changes i had to make.

add + symbol before new

And major issue which i should have picked before itself was it should be a.snippet.publishedAt instead of a.publishedAt

this.videoComments.forEach(comment => {
   if(!!comment.replies) {
         comment.replies.comments = comment.replies.comments.sort((a, b) => +new Date(b.snippet.publishedAt) - +new Date(a.snippet.publishedAt));
   }
});

Once again Thanks a lot