0

I have a table including 6 columns which contains data from a root array:

  columns: any[] = [{ sortBy: 'startTime', title: 'Order Date' }, { sortBy: 'btcAmount', title: 'BTC' },
  { sortBy: 'btcPrice', title: 'Rate' }, { sortBy: 'total', title: 'Total' },
  { sortBy: 'status', title: 'Status' }, { sortBy: 'paymentResult.updated', title: 'Payment Date' }];

The first 5 columns are able to sort properly, while the last column Payment Date sorted by paymentResult.updated contains data as a nested property in the same root array (this.transactions) that is not able to sort accordingly. This is my sort function:

sort(property = 'startTime') {
    this.column = property;
    this.isDesc = !this.isDesc;
    this.direction = this.isDesc ? 1 : -1;
    this.transactions.sort((a, b) => {
      if (a === null) return -1;
      if (b === null) return 1;
      if (a[property] === b[property]) return 0;
      return a[property] < b[property] ? -1 * this.direction : 1 * this.direction;
    });
  } 

This is the data structure of the array:

{
  "id": "string",
  "status": "Open",
  "startTime": "2017-12-11T09:43:45.534Z",
  "validUntil": "2017-12-11T09:43:45.534Z",
  "btcAmount": 0,
  "btcPrice": 0,
  "total": 0,
  "paymentResult": {
    "id": "string",
    "status": "Paid",
    "updated": "2017-12-11T09:43:45.534Z"
  }      
}

This is the view:

<table class="table table-responsive table-hover" *ngIf="transactions" >
        <thead class="thead-default">
          <tr>
            <th *ngFor="let columnName of columns" 
                (click)="sort(columnName.sortBy)">
              {{columnName.title}}
            </th>
          </tr>
        </thead>
        <tbody>
          <tr *ngFor="let transaction of transactions>
            <td>{{ transaction.startTime | date: 'short' }}</td>
            <td>{{ transaction.btcAmount.toFixed(6) }}</td>
            <td>{{ transaction.btcPrice | currency:'USD':true }}</td>
            <td>{{ transaction.total | currency:'USD':true }}</td>
            <td>{{ transaction.status }}</td>
            <td> {{transaction.paymentResult?.updated}}</td>
          </tr>
        </tbody>
      </table>

1 Answer 1

1

Kind of this I guess - just check whether it is nested property, if yes - iterate properties one by one till find the value:

sort(property = 'startTime') {
    this.column = property;
    this.isDesc = !this.isDesc;
    this.direction = this.isDesc ? 1 : -1;
    this.transactions.sort((a, b) => {
    let a1 = a;
    let b1 = b;
    if(property.indexOf('.') > -1) {
     let keys = property.split('.');
     keys.forEach((key) => {
       if(a1 == null) return -1;
       if (b1 === null) return 1;
       a1 = a1[key];
       b1 = b1[key];
     })
    }
      if (a === null) return -1;
      if (b === null) return 1;
      if (a1 === b1) return 0;
      return a[property] < b[property] ? -1 * this.direction : 1 * this.direction;
    });
  } 

Not tested, but the idea is clear.

Sign up to request clarification or add additional context in comments.

2 Comments

this is a nice idea, but the property this.transactions.paymentResult sometimes can be null, so the console will return error like Cannot read property 'updated' of null
I made a solution by mapping the nested property into a not-nested property then I can sort the array as usual. Thank you for you solution anyway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.