Home > other >  Get max value from Angular Material Table / JSON array
Get max value from Angular Material Table / JSON array

Time:03-17

I have created a function to map over a json data to display it as a table using Angular Material. I would like to

  1. Display the highest bidamt and the corresponding from my table in my and
  2. Currently my id is arranged in order of timing (i.e. an earlier entry is displayed as 1, a later entry is displayed as 2 etc.). How can I rearrange it to display it in order from highest to lowest bid?

bid.component.html

<div >
        <div >
            <span >{{bid.bidamt | max}}</span>
            <span >{{bid.name | max}}</span>
        </div>
        <table mat-table [dataSource]="dataSource"  
        matSort matSortDisableClear matSortActive="bidamt" matSortDirection="desc">
          <ng-container matColumnDef="id">
            <th mat-header-cell *matHeaderCellDef mat-sort-header> No.</th>
            <td mat-cell *matCellDef="let bid"> {{bid.id}} </td>
          </ng-container>
           <ng-container matColumnDef="bidamt">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>Bids</th>
            <td mat-cell *matCellDef="let bid"> {{bid.bidamt | number}} UCD</td>
          </ng-container>
          <ng-container matColumnDef="bidname">
            <th mat-header-cell *matHeaderCellDef>Name</th>
            <td mat-cell *matCellDef="let bid"> {{bid.bidname}} </td>
          </ng-container>
          <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
          <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
        </table>
        <mat-paginator
          style="color: rgba(255,255,255,0.7)"
          [pageSize]="2"
          [pageSizeOptions]="[2, 5, 10]"
          aria-label="Select page">
        </mat-paginator>
      </div>

bid.json

{
  "bids": [
    {
      "bidamt": 500,
      "bidname": "Alice",
      "id": 1
    },
    {
      "bidamt": 300,
      "bidname": "Ben",
      "id": 2
    },
    {
      "bidamt": 2000,
      "bidname": "Clare",
      "id": 3
    }
  ]
}

bid.component.ts

export class BidComponent implements OnInit, OnDestroy, AfterViewInit { 
  displayedColumns: string[] = ['id', 'bidamt', 'name'];
  dataSource!:MatTableDataSource<any>;

  @ViewChild('paginator') paginator! : MatPaginator; 
  @ViewChild(MatSort) matSort! : MatSort;

  subscription: Subscription = new Subscription;

  constructor(private BidService: BidService){ }

  async ngOnInit() {
    this.BidService.getBids().subscribe((response:any) =>{
        this.dataSource = new MatTableDataSource(response);
        this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.matSort;
      })
  }

}

CodePudding user response:

You have two approach:

  1. Sort the array before create the data source

    this.dataSource = new MatTableDataSource(response
                            .sort((a,b)=>a.bidamt-b.bidamt));
    
  2. Create a function like

      sortTable(active:string,direction:string)
      {
        this.sort.active=active
        this.sort.direction=direction as SortDirection
        this.sort.sortChange.emit(
               {active: active, direction: direction as SortDirection});
      }
    

    And call after asign the sort

    ...
    this.dataSource.sort = this.matSort;
    this.sortTable('bidamt','asc')
    

To know the max and store in a variable. first declare

max:number=0

then, simple use reduce of the array in subscribe

 this.BidService.getBids().subscribe((response:any) =>{
    this.dataSource = new MatTableDataSource(response);
    this.max=response.reduce((a,b)=>b.bidamt>a?b.bidamt:a,-1000)
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.matSort; //<--add this line
  })

Then you can use to add a class in the row

   <tr mat-row [class.highest-amt-name]="row.bidamt==max" 
        *matRowDef="let row; columns: displayedColumns;"></tr>

or using style-background

   <tr mat-row [style.background-color]="row.bidamt==max?'red':null" 
        *matRowDef="let row; columns: displayedColumns;"></tr>
   

If you want to use in a span you simply use

  {{max}}

Update we can add a new property "order" (or reemplace the "id" by order) using simply sort and map, e.g.

response=response.sort((a,b)=>a.bidamt-b.bidamt)
        .map((x:any,i:number)=>({...x,order:i}))
//or
response=response.sort((a,b)=>a.bidamt-b.bidamt)
        .map((x:any,i:number)=>({...x,id:i}))

See how we use the spread operator (the ...x) to create an object with all the properties of the object and a new property "order" or a change of the property "id")

update 2 if we want to get the "element" with a "bidamt" greater. Using reduce we can do

this.max=response.reduce((a,b)=>b.bidamt>a.bidamt?b:a,response[0])

Well, if we already have the array sorted is simple

    reduce[0] //the first element or 
    reduce[reduce.length-1]  //the last element

in this case max is an object, so to compare the row we need use max.bidmat

  <tr mat-row [style.background-color]="row.bidamt==max.bidmat?'red':null" 
    *matRowDef="let row; columns: displayedColumns;"></tr>
  • Related