角度材质表 - 排序箭头在 mat-sort-header 中无法正确显示

问题描述 投票:0回答:1

我正在开发一个 Angular 项目,在该项目中我使用 Angular Material 的 mat-table 并启用了排序。排序功能有效,但当我使用 ts 代码更改排序时,列标题中的箭头无法正确显示。

HTML:

<div class="cpage">
  <div class="left-margin"></div>
  <div class="left">
    <form-card header="Left" [enableBottomPadding]="true">
      <button mat-raised-button (click)="actionB1()">B1</button>
    </form-card>
  </div>
  <div class="gap-between"></div>
  <div class="right">
    <form-card header="DataTable" [enableBottomPadding]="true">
      <div style="width: 100%; max-height:90vh; overflow-x:auto">
        <mat-table [dataSource]="dataSource" matSort #sort1="matSort">
          <ng-container matColumnDef="position">
            <mat-header-cell mat-sort-header *matHeaderCellDef> No.</mat-header-cell>
            <mat-cell *matCellDef="let element"> {{ element.position }}</mat-cell>
          </ng-container>

          <ng-container matColumnDef="name">
            <mat-header-cell mat-sort-header *matHeaderCellDef> Name</mat-header-cell>
            <mat-cell *matCellDef="let element"> {{ element.name }}</mat-cell>
          </ng-container>

          <ng-container matColumnDef="weight">
            <mat-header-cell mat-sort-header *matHeaderCellDef> Weight</mat-header-cell>
            <mat-cell *matCellDef="let element"> {{ element.weight }}</mat-cell>
          </ng-container>

          <!-- additional weight columns -->
          <ng-container matColumnDef="weight1">
            <mat-header-cell *matHeaderCellDef> Weight</mat-header-cell>
            <mat-cell *matCellDef="let element"> {{ element.weight }}</mat-cell>
          </ng-container>

          <ng-container matColumnDef="symbol">
            <mat-header-cell *matHeaderCellDef> Symbol</mat-header-cell>
            <mat-cell *matCellDef="let element"> {{ element.symbol }}</mat-cell>
          </ng-container>

          <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
          <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
        </mat-table>
      </div>
    </form-card>
  </div>
  <div class="right-margin"></div>
</div>

TS:

import { AfterViewInit, ChangeDetectorRef, Component, ViewChild } from '@angular/core';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from "@angular/material/table";

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
  { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
  { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
  { position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
  { position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
  { position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
  { position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
  { position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
  { position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
  { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
];

@Component({
  selector: 'app-debug-table',
  templateUrl: './debug-table.component.html',
  styleUrls: ['./debug-table.component.scss']
})
export class DebugTableComponent implements AfterViewInit {
  displayedColumns: string[] = ['position', 'name', 'weight', 'weight1', 'symbol'];
  dataSource = new MatTableDataSource(ELEMENT_DATA);
  @ViewChild('sort1', { static: false }) sort1: MatSort;

  constructor(private cdr: ChangeDetectorRef) {}

  ngAfterViewInit() {
    this.dataSource.sort = this.sort1;
  }

  actionB1() {
    if (this.sort1.active == 'name') {
      this.sort1.active = 'weight';
    } else {
      this.sort1.active = 'name';
    }
    this.dataSource.sort = this.sort1;
    this.cdr.detectChanges();
  }
}

问题:排序有效,但列标题旁边的排序箭头无法正确更新。单击“B1”按钮可在“名称”和“重量”之间切换排序,但 mat-sort-header 标题上的箭头似乎不遵循此切换。

我尝试过的:

已验证我已导入 Angular Material 排序模块。 检查 matSort 和 mat-sort-header 是否正确添加到 mat-table 和标题单元格中。 更新排序后调用 detectorChanges 来尝试刷新视图。 以前有人遇到过这个问题吗?关于如何让箭头正确显示有什么想法吗?

角度:16 角度材质:16

angular sorting angular-material angular-material-table
1个回答
0
投票

您可以使用

sort
dataSource.sort
方法,它接受
MatSortable
的接口输入。

export declare interface MatSortable {
    /** The id of the column being sorted. */
    id: string;
    /** Starting sort direction. */
    start: SortDirection;
    /** Whether to disable clearing the sorting state. */
    disableClear: boolean;
}

export declare type SortDirection = 'asc' | 'desc' | '';

然后我们就可以使用下面的方法了。

actionB1() {
  let active = null;
  if (this.sort1.active == 'name') {
    active = 'weight';
  } else {
    active = 'name';
  }
  this.dataSource.sort!.sort({
    id: active,
    start: 'asc',
    disableClear: true,
  });
  // this.cdr.detectChanges();
}

完整代码:

HTML:

<button mat-raised-button (click)="actionB1()">B1</button>
<table
  mat-table
  matSort
  [dataSource]="dataSource"
  class="mat-elevation-z8"
  (matSortChange)="sortData($event)"
>
  <!--- Note that these columns can be defined in any order.
        The actual rendered columns are set as a property on the row definition" -->

  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef mat-sort-header="position">No.</th>
    <td mat-cell *matCellDef="let element">{{element.position}}</td>
  </ng-container>

  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef mat-sort-header="name">Name</th>
    <td mat-cell *matCellDef="let element">{{element.name}}</td>
  </ng-container>

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <th mat-header-cell *matHeaderCellDef mat-sort-header="weight">Weight</th>
    <td mat-cell *matCellDef="let element">{{element.weight}}</td>
  </ng-container>

  <!-- Symbol Column -->
  <ng-container matColumnDef="symbol">
    <th mat-header-cell *matHeaderCellDef mat-sort-header="symbol">Symbol</th>
    <td mat-cell *matCellDef="let element">{{element.symbol}}</td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

TS:

import { Component, ViewChild, ChangeDetectorRef, inject } from '@angular/core';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';
import { MatSortModule, Sort } from '@angular/material/sort';

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
  { position: 2, name: 'Helium', weight: 4.0026, symbol: 'He' },
  { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
  { position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
  { position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
  { position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
  { position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
  { position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
  { position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F' },
  { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
];

function compare(a: number | string, b: number | string, isAsc: boolean) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

/**
 * @title Basic use of `<table mat-table>`
 */
@Component({
  selector: 'table-basic-example',
  styleUrl: 'table-basic-example.css',
  templateUrl: 'table-basic-example.html',
  standalone: true,
  imports: [MatTableModule, MatSortModule],
})
export class TableBasicExample {
  displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
  dataSource = new MatTableDataSource(ELEMENT_DATA);
  cdr = inject(ChangeDetectorRef);
  @ViewChild(MatSort, { static: false }) sort1: MatSort;

  ngAfterViewInit() {
    this.dataSource.sort = this.sort1;
  }

  actionB1() {
    let active = null;
    if (this.sort1.active == 'name') {
      active = 'weight';
    } else {
      active = 'name';
    }
    this.dataSource.sort!.sort({
      id: active,
      start: 'asc',
      disableClear: true,
    });
    // this.cdr.detectChanges();
  }

  sortData(sort: Sort) {
    const data = this.dataSource.data.slice();
    if (!sort.active || sort.direction === '') {
      this.dataSource.data = data;
      return;
    }

    this.dataSource.data = data.sort((a, b) => {
      const isAsc = sort.direction === 'asc';
      switch (sort.active) {
        case 'name':
          return compare(a.name, b.name, isAsc);
        case 'weight':
          return compare(a.weight, b.weight, isAsc);
        case 'symbol':
          return compare(a.symbol, b.symbol, isAsc);
        default:
          return 0;
      }
    });
  }
}

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.