Sắp xếp các cột trong bảng trong Angular
Tôi đang cố gắng sắp xếp các cột trong bảng của mình. Tôi tìm thấy hướng dẫn này ở đây:https://www.youtube.com/watch?v=UzRuerCoZ1E&t=715s
Sử dụng thông tin đó, tôi đã kết thúc với những điều sau:
Một đường ống xử lý việc phân loại
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'sort',
pure: true
})
export class TableSortPipe implements PipeTransform {
transform(list: any[], column:string): any[] {
let sortedArray = list.sort((a,b)=>{
if(a[column] > b[column]){
return 1;
}
if(a[column] < b[column]){
return -1;
}
return 0;
})
return sortedArray;
}
}
Đây là thành phần giúp tôi xây dựng bảng của mình. Ở đây tôi xác định biến sortedColumn.
import { NavbarService } from './../navbar/navbar.service';
import { LiveUpdatesService } from './live-updates.service';
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
@Component({
selector: 'app-live-updates',
templateUrl: './live-updates.component.html',
styleUrls: ['./sass/live-updates.component.scss']
})
export class LiveUpdatesComponent implements OnInit{
stocks$: Observable<any[]>; sortedColumn: string; constructor(private updatesService: LiveUpdatesService, public nav: NavbarService) { this.stocks$ = this.updatesService.getStocks();
}
ngOnInit() {
this.nav.show();
}
}
Đây là tệp mẫu của tôi. Như bạn có thể thấy, tôi đã gắn sortđường ống của mình vào vòng lặp của mình, loại bỏ các hàng trong bảng. Cần lưu ý rằng cách tôi hiển thị bảng khác với video. Ví dụ: dữ liệu của anh ấy được lưu trữ trong một mảng, nhưng của tôi được lưu trữ trên Firebase. Anh ấy đang hiển thị bảng của mình một cách động, nhưng của tôi được cố định vào một số cột nhất định. Tôi cũng đang mã hóa các tiêu đề, nhưng anh ta đã sử dụng các tên biến từ mảng của mình để tạo tiêu đề bảng. Tôi không chắc liệu những khác biệt này có thể ngăn cản mọi thứ hoạt động hay không.
<section class="score-cards">
<app-score-cards></app-score-cards>
</section>
<section class="live-updates-wrapper">
<div class="table-wrapper">
<table class="stock-updates">
<thead>
<tr>
<th class="ticker-fixed">Ticker</th>
<th><a (click)="sortedColumn = $any($event.target).textContent">Ask Price</a></th>
<th><a (click)="sortedColumn = $any($event.target).textContent">Tax Value</a></th>
<th><a (click)="sortedColumn = $any($event.target).textContent">Est. Value</a></th>
<th><a (click)="sortedColumn = $any($event.target).textContent">Location</a></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let s of stocks$ | async | sort : sortedColumn">
<td class="ticker-fixed">
<a target="_blank" href="https://robinhood.com/stocks/{{ s.TICKER }}">{{ s.TICKER }}</a>
<span class="sp500">{{ s.sp500_flag }}S&P</span>
</td>
<td>{{ s.CLOSE }}</td>
<td>{{ s.tax_diff }}</td>
<td>{{ s.MarketCap }}</td>
<td>{{ s.Sector }}</td>
</tr>
</tbody>
</table>
</div>
</section>
Tôi đã gặp lỗi sau đây bên dưới, nhưng đã có thể khắc phục nó bằng cách đưa mã sau vào tệp đường dẫn của tôi: list = !!list ? list : [];
Bây giờ không có lỗi, nhưng việc sắp xếp không hoạt động như mong đợi. Khi tôi nhấp vào tiêu đề bảng, không có gì xảy ra. Làm thế nào tôi có thể sửa lỗi này?
Trả lời
quên đường ống. phân loại thông qua đường ống là một thực tiễn không tốt, dẫn đến mã lỗi hoặc hiệu suất kém.
Thay vào đó, hãy sử dụng vật có thể quan sát.
trước tiên hãy thay đổi các nút tiêu đề mẫu của bạn để gọi một hàm và cũng đảm bảo rằng bạn đang cung cấp các tên thuộc tính thực tế mà bạn muốn sắp xếp, thay vì nội dung tiêu đề:
<th><a (click)="sortOn('CLOSE')">Ask Price</a></th>
<th><a (click)="sortOn('tax_diff')">Tax Value</a></th>
<th><a (click)="sortOn('MarketCap')">Est. Value</a></th>
<th><a (click)="sortOn('Sector')">Location</a></th>
sau đó, kéo chức năng sắp xếp của bạn ra và nhập vào thành phần của bạn:
export function sortByColumn(list: any[] | undefined, column:string, direction = 'desc'): any[] {
let sortedArray = (list || []).sort((a,b)=>{
if(a[column] > b[column]){
return (direction === 'desc') ? 1 : -1;
}
if(a[column] < b[column]){
return (direction === 'desc') ? -1 : 1;
}
return 0;
})
return sortedArray;
}
sau đó sửa thành phần của bạn:
// rx imports
import { combineLatest, BehaviorSubject } from 'rxjs';
import { map, scan } from 'rxjs/operators';
...
export class LiveUpdatesComponent implements OnInit{
stocks$: Observable<any[]>; // make this a behavior subject instead sortedColumn$ = new BehaviorSubject<string>('');
// the scan operator will let you keep track of the sort direction
sortDirection$ = this.sortedColumn$.pipe(
scan<string, {col: string, dir: string}>((sort, val) => {
return sort.col === val
? { col: val, dir: sort.dir === 'desc' ? 'asc' : 'desc' }
: { col: val, dir: 'desc' }
}, {dir: 'desc', col: ''})
)
constructor(private updatesService: LiveUpdatesService, public nav: NavbarService) {
// combine observables, use map operator to sort
this.stocks$ = combineLatest(this.updatesService.getStocks(), this.sortDirection$).pipe(
map(([list, sort]) => !sort.col ? list : sortByColumn(list, sort.col, sort.dir))
);
}
// add this function to trigger subject
sortOn(column: string) {
this.sortedColumn$.next(column);
}
ngOnInit() {
this.nav.show();
}
}
cuối cùng, hãy sửa ngFor:
<tr *ngFor="let s of stocks$ | async">
theo cách này, bạn không dựa vào phép thuật hoặc phát hiện thay đổi. bạn đang kích hoạt phân loại của mình khi nó cần kích hoạt thông qua vật có thể quan sát
Tôi nghĩ rằng các giá trị của bạn không được truyền vào đường ống:
Bạn có thể thử:
<tr *ngFor="let s of ((stocks$ | async) | sort : sortedColumn)">
Asyn gọi overhere trước khi gán this.stocks$bảng giá trị sẽ tải đường ống sẽ được gọi
constructor(private updatesService: LiveUpdatesService, public nav: NavbarService) {
this.stocks$ = this.updatesService.getStocks();
}
Bản mẫu
<tbody *ngIf="stocks$"> <tr *ngFor="let s of stocks$ | sort : sortedColumn">
....
</tr>
</tbody>