【问题标题】:How can I solve this Error and why it occured?我该如何解决这个错误以及它发生的原因?
【发布时间】:2019-05-18 10:31:02
【问题描述】:

使用排序标题实现 AngularMaterial 表我在控制台中收到此错误:

错误类型错误:无法设置未定义的属性“排序” 在

终端中的这个错误:

错误 TS2740:“MatTableDataSource”类型缺少“Employee[]”类型的以下属性:length、pop、push、concat 等 24 个。

错误 TS2322:类型 'MatSort' 不可分配给类型 '(compareFn?: (a: Employee, b: Employee) => number) => Employee[]'。

类型“MatSort”不匹配签名“(compareFn?: (a: Employee, b: Employee) => number): Employee[]”。

我无法从我这里得到它想要的东西。我将不胜感激任何提示!

我使用了 AngularMaterial 文档中的代码,但数据接口除外。这可能是一个问题吗?

员工列表组件


import { Component, OnInit, ViewChild } from '@angular/core';
import { MatSort, MatTableDataSource } from '@angular/material';
import { AngularFirestore } from '@angular/fire/firestore';
import { EmployeeService } from '../shared/employee.service';
import { Employee } from '../shared/employee';

@Component({
  selector: 'app-employee-list',
  templateUrl: './employee-list.component.html',
  styleUrls: ['./employee-list.component.scss']
})
export class EmployeeListComponent implements OnInit {

  displayedColumns: string[] = ['fullname', 'position', 'mobile'];
  dataSource;

  @ViewChild(MatSort) sort: MatSort;

  constructor(private service: EmployeeService) { }

  ngOnInit() {
    this.service.getEmployees().subscribe(employees => {
      this.dataSource = new MatTableDataSource(employees);
      console.log(this.dataSource);
    });
    this.dataSource.sort = this.sort;

  }

}


员工列表 HTML


<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">

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

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

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

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


员工服务


getEmployees() {
    return this.firestore.collection<Employee>('employees')
      .snapshotChanges()
      .pipe(
        map(actions => actions.map(a => {
          const data = a.payload.doc.data();
          const id = a.payload.doc.id;
          return { id, ...data } as Employee;
       })
        )
      );
}

员工类


export class Employee {
  id: string;
  fullname: string;
  empCode: string;
  position: string;
  mobile: string;
}


【问题讨论】:

  • 您可以尝试设置排序操作的超时时间,直到获取数据为止,方法是在 console.log之后的 ngOnInit 内添加 setTimeout(() =&gt; this.dataSource.sort= this.sort); > 线。
  • setTimeout() 工作了吗?
  • @Karthik_Siddh 我已经用 ngAfterViewInit 解决了这个问题,并将一些代码移到了订阅部分。解决了错误问题的方法对我很有用,但由于某些原因我的排序仍然不起作用。也许你知道为什么?我将不胜感激任何提示

标签: angular angular-material frontend angular-material-7


【解决方案1】:

您正在尝试从订阅外部访问数据,它应该在订阅内部。

在此之后,您将遇到this.sortngOnInit 挂钩中未定义的问题,这是因为您试图访问尚未绘制的HTML 元素。 (MatSort)

有一个生命周期钩子可以用来确保视图已准备好被@ViewChild 访问,这是 ngAfterViewInit,仅在绘制 HTML 时触发。

尝试像这样构造。


import { Component, AfterViewInit, ViewChild } from '@angular/core';
import { MatSort, MatTableDataSource } from '@angular/material';
import { AngularFirestore } from '@angular/fire/firestore';
import { EmployeeService } from '../shared/employee.service';
import { Employee } from '../shared/employee';

@Component({
  selector: 'app-employee-list',
  templateUrl: './employee-list.component.html',
  styleUrls: ['./employee-list.component.scss']
})
export class EmployeeListComponent implements AfterViewInit{

  displayedColumns: string[] = ['fullname', 'position', 'mobile'];
  dataSource;

  @ViewChild(MatSort) sort: MatSort;

  constructor(private service: EmployeeService) { }

  ngAfterViewInit(): void
  {
    this.service.getEmployees().subscribe(employees => {
      this.dataSource = new MatTableDataSource(employees);
      if (this.sort) // check it is defined.
      {
          this.dataSource.sort = this.sort;
      }
    });
  }

}

文档AfterViewInit Lifecycle // More details.

【讨论】:

  • 谢谢!它有助于解决错误,但我的排序仍然不起作用:/我已经将所有内容与文档中的原始代码进行了比较 - 一切都是一样的。可能是什么问题?
  • 我不是 100% 使用材料位,只是为更多角度相关的错误提供我的帮助。您的数据是否符合 mat 排序的预期?
  • 我猜是这样 ? 它用我拥有的数据构建了我的表。 AngularMaterial 需要一个包含数据的数组。我懂了。原因可能是使用 Employee 接口以外的 Employee 类吗?这是我能看到的唯一区别。我在 mat-table 上使用了所有标签 matSort,在 mat-h​​eader-cell 上使用了 may-sort-header
  • 请在您的数据中编辑问题,您定义的类的形状将查看
  • 我的错! :D 我应该将 MatSortModule 导入我的模块。我检查了文档。再次感谢!
【解决方案2】:

总体而言,您的代码看起来还可以,但是这一行

this.dataSource.sort = this.sort;

位置不对,应该放在subscribe块内。

原因ERROR TypeError: Cannot set property 'sort' of undefined

您正在将同步代码与异步混合,我的意思是您的 subscribe 代码只会在 API 的响应返回时执行(1 到 2 秒),但 this.dataSource.sort = this.sort; 不会等待响应,因为它是同步的无论有任何HTTP 请求,它都会继续执行,并且您的dataSource 对象将是undefined,因此您需要将其移入异步部分。

你的代码应该是这样的:

ngOnInit() {
    this.service.getEmployees().subscribe(employees => {
      this.dataSource = new MatTableDataSource(employees);
      console.log(this.dataSource);
      this.dataSource.sort = this.sort; <- note this line 

   });   
}

【讨论】:

  • 是的,一个愚蠢的错误?非常感谢!你使用 AngularMaterial 吗?
  • 您的解决方案有助于解决错误问题,但我的排序仍然无法正常工作:/ 可能是什么问题?我知道在我的情况下可能有什么?但仍然有任何提示吗?
猜你喜欢
  • 1970-01-01
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-21
  • 2016-09-09
相关资源
最近更新 更多