【问题标题】:Angular matSort does not sort角度 matSort 不排序
【发布时间】:2018-03-28 22:41:09
【问题描述】:

我在将 matSort 导入我的 matTable 时遇到问题。

我正在为您提供我的代码:

dashboard.component.ts

import {Component, ViewChild} from '@angular/core';
import {UserService} from "../user.service";
import {DohvatMantisaService} from "../dohvat-mantisa.service";
import {Mantisi} from "../Mantisi";
import {Observable} from "rxjs/Observable";
import {DataSource} from "@angular/cdk/collections";
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import {MatSort} from '@angular/material';
@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent{
  displayedColumns = ['projekt', 'manits', 'kategorija','ozbiljnost','datum_prijave','postavio','odjel','postavio','naziv','status','planirana_isporuka'];
  constructor(private user:UserService, private dohvatMantisa:DohvatMantisaService) {
  }
  dataSource: TableDataSource | null;
  mantisi: Mantisi[];
  name = this.user.getUsername();
  @ViewChild(MatSort) sort: MatSort;
  ngOnInit() {
    this.dataSource = new TableDataSource(this.dohvatMantisa,this.sort);
  }
}

export class TableDataSource extends DataSource<Mantisi>{
  constructor(private mantisiDS: DohvatMantisaService,private sort: MatSort){
    super();
  }
  connect(): Observable<Mantisi[]> {
    const displayDataChanges = [
      this.mantisiDS.dohvatiMantise(),
      this.sort.sortChange,
    ];

    return Observable.merge(...displayDataChanges).map(() => {
      return this.getSortedData();
    });
  }
  disconnect() {}

  getSortedData(): Mantisi[]{
    const data = this.mantisiDS.prikazMantisa().slice();
    if (!this.sort.active || this.sort.direction == '') { return data; }
    return data.sort((a, b) => {
      let propertyA: number|string = '';
      let propertyB: number|string = '';
      switch (this.sort.active) {
        case 'projekt': [propertyA, propertyB] = [a.projekt, b.projekt]; break;
        case 'manits': [propertyA, propertyB] = [a.manits, b.manits]; break;
        case 'kategorija': [propertyA, propertyB] = [a.kategorija, b.kategorija]; break;
        case 'ozbiljnost': [propertyA, propertyB] = [a.ozbiljnost, b.ozbiljnost]; break;
        case 'datum_prijave': [propertyA, propertyB] = [a.datum_prijave, b.datum_prijave]; break;
        case 'postavio': [propertyA, propertyB] = [a.postavio, b.postavio]; break;
        case 'naziv': [propertyA, propertyB] = [a.naziv, b.naziv]; break;
        case 'status': [propertyA, propertyB] = [a.status, b.status]; break;
        case 'planirana_isporuka': [propertyA, propertyB] = [a.planirana_isporuka, b.planirana_isporuka]; break;
      }

      let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
      let valueB = isNaN(+propertyB) ? propertyB : +propertyB;

      return (valueA < valueB ? -1 : 1) * (this.sort.direction == 'asc' ? 1 : -1);
    });
  }
}

这是我的服务: dohvatMantisaService

import { Injectable } from '@angular/core';
import {Http, Response, RequestOptions, Headers} from "@angular/http";
import {Observable} from "rxjs/Observable";
import {Mantisi} from "./Mantisi";
import 'rxjs';
import 'rxjs/operator/map';
import 'rxjs/operator/do';

@Injectable()
export class DohvatMantisaService {
  constructor(public http:Http) { }
  result: Mantisi[];
  dohvatiMantise(): Observable<Mantisi[]>{
    return this.http.get('/mantis/getMantisReport').map(this.extractData);
  }
  private extractData(response: Response) {
    let body = response.json();
    return body || {};
  }

  prikazMantisa(): Mantisi[]{
    this.dohvatiMantise().subscribe(res => this.result = res);
    return this.result;
  }
}

我为您提供了我的dashboard.component.html matSort 行:

<mat-table #table [dataSource]="dataSource" class="example-table" matSort>

这里的主要问题是数据是从 http 请求加载和获取的,但我在控制台中遇到如下错误:

无法读取未定义的属性“sortChange” 在 TableDataSource.webpackJsonp.../../../../../src/app/dashboard/dashboard.component.ts.TableDataSource.connect (dashboard.component.ts:36) 在 MatTable.webpackJsonp.../../../cdk/esm5/table.es5.js.CdkTable._observeRenderChanges (table.es5.js:602) 在 MatTable.webpackJsonp.../../../cdk/esm5/table.es5.js.CdkTable.ngAfterContentChecked (table.es5.js:522)

它告诉我 this.sort.sortChange 是未定义的。 我搜索了所有互联网,找不到正确的答案。希望你能帮助我。

【问题讨论】:

    标签: angular angular-material


    【解决方案1】:

    除了所有其他答案,如果您的模板中有多个带有排序的表,则需要定义唯一的matSort,如下所示:

    模板:

    <mat-table [dataSource]="firstDataSource" matSort #firstSort="matSort">
    

    组件:

    @ViewChild('firstSort', { static: false }) firstSort: MatSort;
    
    ngAfterViewInit() {
       this.firstDataSource.sort = this.firstSort;
    }
    

    【讨论】:

      【解决方案2】:

      对我来说,我忘了把matSort 属性放在&lt;table/&gt; 上。

      <table mat-table matSort [dataSource]="dataSource">
      

      【讨论】:

        【解决方案3】:

        如果数据在对象内,排序也不起作用。例如:

        interface: Name { firstName: string; lastName: string; }
        interface: User { name: Name; }
        
        {{ user.Name.firstName }}
        

        在这种情况下,排序不起作用。它需要像:{{ user.firstName }}

        此外,属性名称和列名称必须匹配。

        【讨论】:

          【解决方案4】:

          我刚刚遇到了这个问题,我所要做的就是确保您正确引用了您的 matSort viewChild,并确保您已在导入区域的 module.ts 文件中添加了 MatSortModule

          如下:

          @NgModule({
            imports: [
              MatSortModule,
              MatTableModule,
            ]
          )}
          

          【讨论】:

          • 很有帮助,但是已经导入了。如果没有模块导入,您会收到诸如“您是否考虑将 matSort 实现到 @NgModule 的声明中?”之类的错误。另外,我已经发布了解决方案,您可以检查一下。
          • 实际上,没有模块导入我没有收到任何错误。它只是无法工作,因为在我尝试设置 sort 变量时未定义 MatSort。
          • Google 并不擅长编写文档,因此仅按照他们的示例,他们的代码就可以正常工作。这是我的问题。谢谢。
          • 只需将 MatSortModule 添加到 NgModule 导入中。之后它就开始工作了。
          • 我的问题是一样的
          【解决方案5】:

          对于 Angular 8 和 Material 6.4.1,如果您等待从服务接收数据,修复 MatSort 和 MatPaginator 的最简单和最好的方法是设置 static: false 而不是 true,像这样:

          @ViewChild(MatSort, { static: false }) sort: MatSort;
          @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator;
          

          在我的例子中是一个 ngOnChanges 数据调用。

          【讨论】:

          • this.dataSource.sort = this.sort 放入ngOnChanges 对我来说对异步MatTableDataSource 有效。此外,{static: false} 是默认值,因此您不必显式声明它。
          【解决方案6】:

          我遇到了同样的问题,

          这个问题有几个原因

          1. 确保您的 App 模块 中包含 MatSortModule 模块
           import { MatSortModule, MatPaginatorModule, MatTableModule } from '@angular/material';
          
           @NgModule({
            imports: [MatSortModule, MatPaginatorModule, MatTableModule],
            exports: []
          })
          
          1. 确保您已订阅 ngAfterViewInit 中的排序更改
            ngAfterViewInit() {
              this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0 );
            }
          

          【讨论】:

            【解决方案7】:

            之所以会这样,是因为您的 this.sort.sortChange 方法在您的子视图 Initialize 之前被调用

            您只需要从 AfterViewInit 而不是 OnInit

            实现您的类

            并使用ngAfterViewInit生命周期方法

            export class ApplicantListComponent implements AfterViewInit {
                @ViewChild(MatPaginator, { static: false }) paginator: MatPaginator;
                @ViewChild(MatSort, { static: false }) sort: MatSort;
            
                constructor() {}
            
                ngAfterViewInit() {
                    this.sort.sortChange.subscribe(() => {
                        this.paginator.pageIndex = 0;
                        this.paginator.pageSize = this.pageSize;
                    });
            } 
            

            【讨论】:

            • 只有您的解决方案对我有帮助。谢谢!
            【解决方案8】:

            在将异步数据从容器层传递到组件层时,我遇到了类似的问题。这是我的解决方案

            因为元素开始时没有数据,所以像 original example 那样放置构造函数或 OnInit 是没有用的。只有在数据流进来(异步)之后,我才在 setter 中实现排序和分页器,一切都运行良好。

            在我的模板中:

            <div class="card">
            
                <div class="card-header">
                  <h4>{{pageTitle}}</h4>
                  <mat-form-field>
                    <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
                  </mat-form-field>
                </div>
            
                <div class="card-body p-0">    
                  <div class="mat-elevation-z8">
                    <table mat-table [dataSource]="dataSource" matSort>
            
                      <ng-container matColumnDef="projectNumber">
                        <th mat-header-cell *matHeaderCellDef mat-sort-header> Werf Nummer </th>
                        <td mat-cell *matCellDef="let row"> W{{row.projectNumber}} </td>
                      </ng-container>
            
                      <ng-container matColumnDef="description">
                        <th mat-header-cell *matHeaderCellDef mat-sort-header> Omschrijving </th>
                        <td mat-cell *matCellDef="let row"> {{row.description}} </td>
                      </ng-container>
            
                      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
                      <tr mat-row *matRowDef="let row; columns: displayedColumns;">
                      </tr>
                    </table>
            
                    <mat-paginator [pageSizeOptions]="[10,20,100]"></mat-paginator>
                  </div>      
                </div>
              </div>
            

            在我的角度组件类中,我有

                export class ProjectListComponent {
                  pageTitle = 'Projects';
                  displayedColumns: string[] = ['projectNumber', 'description'];
                  dataSource: MatTableDataSource<Project>;
            
                  @ViewChild(MatPaginator, {static: true}) paginator: MatPaginator;
                  @ViewChild(MatSort, {static: true}) sort: MatSort;
                  @Input() set projects(value: Project[]){
                    this.dataSource = new MatTableDataSource(value);
                    this.dataSource.paginator = this.paginator;
                    this.dataSource.sort = this.sort;
                  }
                  @Input() selectedProject: Project;
                  @Output() selected = new EventEmitter<Project>();
            
                  applyFilter(filterValue: string) {
                    this.dataSource.filter = filterValue.trim().toLowerCase();
            
                    if (this.dataSource.paginator) {
                      this.dataSource.paginator.firstPage();
                    }
                  }
                }
            

            我应该提一下关于过滤选项的其他一些非常有趣的事情。请注意,这里的项目仅用于两个字段,但接口实际上是比这更多的字段,例如它有一个 ID。即使我没有显示 ID,我也可以使用上面的代码按 ID 进行过滤,非常棒。

                export interface Project {
                    id: string;
                    projectNumber: string;
                    description: string;
                    activePeriods: ProjectActivePeriod[];
                }
            

            另请注意,您所显示的列中的 ma​​tColumnDef="projectNumber" 引用必须是界面中属性的确切名称。如果我使用了 'ProjectNumber',排序将不起作用。

            我是根据

            的信息构建的

            【讨论】:

              【解决方案9】:

              我遇到了同样的问题并通过添加以下内容来解决它:

              @ViewChild(MatSort) set matSort(ms: MatSort) {
              this.sort = ms;
              this.setDataSourceAttributes();
               }
              
              @ViewChild(MatPaginator) set matPaginator(mp: MatPaginator) {
               this.paginator = mp;
              this.setDataSourceAttributes();
               }
              
              setDataSourceAttributes() {
                this.dataSource.paginator = this.paginator;
                this.dataSource.sort = this.sort;
                }
              

              【讨论】:

              • 这对我很有帮助。我不是在做分页器,但我在刷新后遇到了排序问题。
              • 这行得通,谢谢。对于 Angular 8,我只需要添加选项 static: false - @ViewChild(MatSort, { static: false }) set matSort(ms: MatSort)
              • { static: false } 当您的数据源为异步时缺少部分!
              • “this.sort=ms”和“this.paginator=mp”出现错误。
              【解决方案10】:

              我已经找到了解决这个问题的方法。

              主要问题是表格在数据到达之前呈现。我首先加载了数据并将其像源一样发送到 dataSource 构造函数。之后,问题就消失了。异步 http.get 和服务就是这样。

              感谢您的帮助。

              fetchData(id){
                this.fetch.getProcesses(id).subscribe(result => {
                  this.processes = result;
                  this.dataSource = new TableDataSource(this.processes);
                  Observable.fromEvent(this.filter.nativeElement, 'keyup')
                    .debounceTime(150)
                    .distinctUntilChanged()
                    .subscribe(() => {
                      if (!this.dataSource) {
                        return;
                      }
                      this.dataSource.filter = this.filter.nativeElement.value;
                    });
                });
              }
              
              
              
              
              export class TableDataSource extends DataSource<Proces>{
                _filterChange = new BehaviorSubject('');
                get filter(): string {
                  return this._filterChange.value;
                }
                set filter(filter: string) {
                  this._filterChange.next(filter);
                }
                filteredData: any =[];
              
                constructor(private processes:Proces[]){
                  super();
                }
                connect(): Observable<Proces[]>{
                  const displayDataChanges = [
                    this.processes,
                    this._filterChange,
                  ];
                  return Observable.merge(...displayDataChanges).map(() => {
                    this.filteredData = this.processes.slice().filter((item: Proces) => {
                      const searchStr = (item.name).toLowerCase();
                      return searchStr.indexOf(this.filter.toLowerCase()) !== -1;
              
                    });
                    return this.filteredData;
                  })
                }
                disconnect(){}
              }
              
              
              
                    <div class="header">
                  <mat-form-field floatPlaceholder="never">
                    <input matInput #filter placeholder="Pretraži procese">
                  </mat-form-field>
                </div>
                <mat-table #table [dataSource]="dataSource" class="table-mantis" matSort>
              
                  <ng-container matColumnDef="col1">
                    <mat-header-cell *matHeaderCellDef class="table-header-cell" mat-sort-header> Name</mat-header-cell>
                    <mat-cell *matCellDef="let row" class="example-cell" > {{row.nazivProcesa}} </mat-cell>
                  </ng-container>
              
                  <ng-container matColumnDef="col2">
                    <mat-header-cell *matHeaderCellDef class="table-header-cell" mat-sort-header> Cell 2</mat-header-cell>
                    <mat-cell *matCellDef="let row" class="example-cell" > {{row.nazivVlasnika
                      }} </mat-cell>
                  </ng-container>
              
                  <ng-container matColumnDef="col3">
                    <mat-header-cell *matHeaderCellDef class="table-header-cell" mat-sort-header> Cell 3</mat-header-cell>
                    <mat-cell *matCellDef="let row" class="example-cell" > {{row.interniAkt}} </mat-cell>
                  </ng-container>
              
                  <mat-header-row *matHeaderRowDef="displayedColumns" class="example-header-row"></mat-header-row>
                  <mat-row class="example-row" *matRowDef="let row; columns: displayedColumns;"></mat-row>
                </mat-table>
              

              【讨论】:

                【解决方案11】:

                如果您使用“*ngIf”在模板中初始隐藏表格容器,则视图框将未定义。

                【讨论】:

                • ¿如果我们需要一个 mat-table 嵌套在带有“*ngIf”的节点中,我们该怎么办?
                • 您可以使用容器并使用 [ngClass]='data !== undefined 吗? "visible": "hidden" ... css 包含类和隐藏 - 在隐藏的情况下 - 元素:.hidden{ visibility: hidden; } .visible{ 可见性:可见; }
                • 这是一个很难找到的问题!
                • 如果可以的话,我会投票 10 次。调试和解决非常困难的问题。这个答案的出色工作@neuralprocessing
                • 非常感谢,至少为我的同事(这里没有足够的评价可以评论)节省了两天的调试时间!
                猜你喜欢
                • 1970-01-01
                • 2021-10-07
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2022-11-25
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多