我试图使用带有Material表的Angular(5)简单地显示来自MySQL数据库的数据。我已成功编译的代码,并出现一个包含列名和分页按钮的表,但表中没有显示数据。我知道API调用正确地返回数据,我知道该服务正在调用API(我可以在浏览器中的网络检查器中看到正确的数据)。
浏览器中显示错误TypeError: _co.unitTypeDatabase.data is undefined
Stack trace:
View_UnitTypeComponent_0/<@ng:///AppModule/UnitTypeComponent.ngfactory.js:136:9 ...
似乎错误是指引用unitTypeDatabase.data.length的html代码中的部分。如果这是未定义的,那么它将解释为什么表中也没有数据。我无法弄清楚的是为什么这是未定义的。我认为这与创建new UnitTypeDatabase
的方式/时间/位置有关,但鉴于服务已成功调用,我不知道从何处开始。这是我的代码:
单元type.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { UnitType } from './unit-type';
import { UnitTypeService } from './unit-type.service';
import {DataSource} from '@angular/cdk/collections';
import {MdPaginator} from '@angular/material';
import {Observable} from 'rxjs/Observable';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
@Component({
selector: 'app-unit-type',
templateUrl: './unit-type.component.html',
styleUrls: ['./unit-type.component.scss'],
providers: [UnitTypeService]
})
export class UnitTypeComponent implements OnInit {
public displayedColumns = ['unitTypeID', 'unitTypeName'];
public unitTypeDatabase: UnitTypeDatabase | null;
public dataSource: UnitTypeDataSource | null;
@ViewChild(MdPaginator) paginator: MdPaginator;
constructor(private unitTypeService: UnitTypeService) {}
ngOnInit() {
this.unitTypeDatabase = new UnitTypeDatabase(this.unitTypeService);
this.dataSource = new UnitTypeDataSource(this.unitTypeDatabase, this.paginator);
}
}
export class UnitTypeDataSource extends DataSource<UnitType> {
constructor(private _unitTypeDatabase: UnitTypeDatabase, private _paginator: MdPaginator) {
super();
}
connect(): Observable<UnitType[]> {
const displayDataChanges = [
this._unitTypeDatabase.dataChange,
this._paginator.page
];
return Observable.merge(...displayDataChanges).map(() => {
const data = this._unitTypeDatabase.data.slice();
const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
return data.splice(startIndex, this._paginator.pageSize);
})
}
disconnect() {}
}
export class UnitTypeDatabase {
/** Stream that emits whenever the data has been modified. */
public dataChange: BehaviorSubject<UnitType[]> = new BehaviorSubject<UnitType[]>([]);
get data(): UnitType[] { return this.dataChange.value; }
constructor(unitTypeService: UnitTypeService) {
unitTypeService.getAllUnitTypes().subscribe(data => this.dataChange.next(data));
}
}
单元type.component.html
<div class="example-container mat-elevation-z8">
<md-table #table [dataSource]="dataSource">
<!-- ID Column -->
<ng-container mdColumnDef="unitTypeID">
<md-header-cell *mdHeaderCellDef> ID </md-header-cell>
<md-cell *mdCellDef="let row"> {{row.unitTypeID}} </md-cell>
</ng-container>
<!-- Name Column -->
<ng-container mdColumnDef="unitTypeName">
<md-header-cell *mdHeaderCellDef> Name </md-header-cell>
<md-cell *mdCellDef="let row"> {{row.unitTypeName}} </md-cell>
</ng-container>
<md-header-row *mdHeaderRowDef="displayedColumns"></md-header-row>
<md-row *mdRowDef="let row; columns: displayedColumns;"></md-row>
</md-table>
<md-paginator #paginator
[length]="unitTypeDatabase.data.length"
[pageIndex]="0"
[pageSize]="25"
[pageSizeOptions]="[5, 10, 25, 100]">
</md-paginator>
</div>
单元type.ts
export class UnitType {
constructor(
public unitTypeID: number,
public unitTypeName: string
){}
}
单元type.service.ts
import { Injectable } from '@angular/core';
import { UnitType } from './unit-type';
import { Headers, Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class UnitTypeService {
private unit_types_Url = 'api/unit-types'; // URL to web api
private headers = new Headers({'Content-Type': 'application/json'});
constructor(private http: Http) { }
getAllUnitTypes(): Observable<UnitType[]> {
return this.http.get(this.unit_types_Url)
.map(response => response.json().data as UnitType[]);
}
}
我从Material网站开始使用示例,但不会使用服务检索数据。我也尝试匹配How to use md-table with services in Angular 4的问答,但我必须遗漏一些东西。希望这是一个明显而简单的错误或误解,有人可以迅速发现。谢谢!
修改 完整的堆栈跟踪是:
ERROR TypeError: _this._unitTypeDatabase.data is undefined
Stack trace:
[208]/UnitTypeDataSource.prototype.connect/<@http://localhost:4200/main.bundle.js:93:17
MapSubscriber.prototype._next@http://localhost:4200/vendor.bundle.js:51417:22
Subscriber.prototype.next@http://localhost:4200/vendor.bundle.js:37214:13
OuterSubscriber.prototype.notifyNext@http://localhost:4200/vendor.bundle.js:48573:9
InnerSubscriber.prototype._next@http://localhost:4200/vendor.bundle.js:117362:9
Subscriber.prototype.next@http://localhost:4200/vendor.bundle.js:37214:13
Subject.prototype.next@http://localhost:4200/vendor.bundle.js:26457:17
BehaviorSubject.prototype.next@http://localhost:4200/vendor.bundle.js:49978:9
UnitTypeDatabase/<@http://localhost:4200/main.bundle.js:122:78
SafeSubscriber.prototype.__tryOrUnsub@http://localhost:4200/vendor.bundle.js:37363:13
SafeSubscriber.prototype.next@http://localhost:4200/vendor.bundle.js:37310:17
Subscriber.prototype._next@http://localhost:4200/vendor.bundle.js:37250:9
Subscriber.prototype.next@http://localhost:4200/vendor.bundle.js:37214:13
MapSubscriber.prototype._next@http://localhost:4200/vendor.bundle.js:51423:9
Subscriber.prototype.next@http://localhost:4200/vendor.bundle.js:37214:13
onLoad@http://localhost:4200/vendor.bundle.js:53409:21
ZoneDelegate.prototype.invokeTask@http://localhost:4200/polyfills.bundle.js:6443:17
onInvokeTask@http://localhost:4200/vendor.bundle.js:4914:24
ZoneDelegate.prototype.invokeTask@http://localhost:4200/polyfills.bundle.js:6442:17
Zone.prototype.runTask@http://localhost:4200/polyfills.bundle.js:6242:28
ZoneTask/this.invoke@http://localhost:4200/polyfills.bundle.js:6496:28
答案 0 :(得分:2)
首先尝试在模板中使用elvis运算符?
。如果只是模板问题,那应该可以解决您的问题。
[length]="unitTypeDatabase?.data?.length"
原因是呈现视图时尚未定义unitTypeDatabase
,因为它仅在ngOnInit()
中初始化。看看是否能解决您的问题。
答案 1 :(得分:0)
问题在于unit-type.service.ts。它应该是:
getAllUnitTypes(): Observable<UnitType[]> {
return this.http.get(this.unit_types_Url)
.map(response => response.json() as UnitType[]);
}
我错过了这样一个事实,即返回的JSON中没有数据对象,因此只要删除了所有信息,所有信息都可见并在表格中正确显示。