我该如何解决这个错误以及它为什么会发生?
How can I solve this Error and why it occured?
实施 AngularMaterial Table 排序 headers 我在控制台中收到此错误:
错误类型错误:无法设置未定义的 属性 'sort'
在
终端出现这个错误:
错误 TS2740:类型 'MatTableDataSource' 缺少类型 'Employee[]' 中的以下属性:长度、弹出、推送、连接和另外 24 个。
错误 TS2322:类型 'MatSort' 不可分配给类型 '(compareFn?: (a: Employee, b: Employee) => number) => Employee[]'。
类型 'MatSort' 没有提供签名匹配 '(compareFn?: (a: Employee, b: Employee) => number): Employee[]'。
我得不到它想要的东西。我将不胜感激任何提示!
除了数据接口外,我使用了 AngularMaterial 文档中的代码。这会成为问题吗?
EmployeeListComponent
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;
})
)
);
}
员工Class
export class Employee {
id: string;
fullname: string;
empCode: string;
position: string;
mobile: string;
}
总的来说你的代码看起来不错,但是这一行
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
});
}
您正在尝试从订阅外部访问数据,它应该在内部。
在此之后,您将 运行 遇到麻烦,因为 this.sort
在 ngOnInit
挂钩中未定义,发生这种情况是因为您试图访问一个 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;
}
});
}
}
实施 AngularMaterial Table 排序 headers 我在控制台中收到此错误:
错误类型错误:无法设置未定义的 属性 'sort' 在
终端出现这个错误:
错误 TS2740:类型 'MatTableDataSource' 缺少类型 'Employee[]' 中的以下属性:长度、弹出、推送、连接和另外 24 个。
错误 TS2322:类型 'MatSort' 不可分配给类型 '(compareFn?: (a: Employee, b: Employee) => number) => Employee[]'。
类型 'MatSort' 没有提供签名匹配 '(compareFn?: (a: Employee, b: Employee) => number): Employee[]'。
我得不到它想要的东西。我将不胜感激任何提示!
除了数据接口外,我使用了 AngularMaterial 文档中的代码。这会成为问题吗?
EmployeeListComponent
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;
})
)
);
}
员工Class
export class Employee {
id: string;
fullname: string;
empCode: string;
position: string;
mobile: string;
}
总的来说你的代码看起来不错,但是这一行
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
});
}
您正在尝试从订阅外部访问数据,它应该在内部。
在此之后,您将 运行 遇到麻烦,因为 this.sort
在 ngOnInit
挂钩中未定义,发生这种情况是因为您试图访问一个 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;
}
});
}
}