angular - 无法使用选项卡式页面上的提供程序在 Angular 和 Ionic 中查询数据库
问题描述
我有一个主页,它是一个用Ionic 3
和设计的选项卡式页面Angular
。它有两个选项卡Stats
和Calc
. 单击 Stats 页面会调用类/组件stats.ts
(如下所示)。
该组件使用两个提供程序CropProvider
,ContractProvider
它们查询数据库并获取一些记录。这些提供程序在其他页面上运行良好,并且能够成功地从 SQLite DB 获取数据,但是通过选项卡式页面我看到了以下错误。
错误:
Error: Uncaught (in promise): TypeError: Cannot read property 'length' of undefined
TypeError: Cannot read property 'length' of undefined
at StatsPage.webpackJsonp.168.StatsPage.buildStats (http://192.168.0.5:8100/build/main.js:707:51)
at new StatsPage (http://192.168.0.5:8100/build/main.js:690:14)
at createClass (http://192.168.0.5:8100/build/vendor.js:13176:20)
at createDirectiveInstance (http://192.168.0.5:8100/build/vendor.js:13011:37)
at createViewNodes (http://192.168.0.5:8100/build/vendor.js:14469:53)
at createRootView (http://192.168.0.5:8100/build/vendor.js:14358:5)
at callWithDebugContext (http://192.168.0.5:8100/build/vendor.js:15783:42)
at Object.debugCreateRootView [as createRootView] (http://192.168.0.5:8100/build/vendor.js:15066:12)
at ComponentFactory_.create (http://192.168.0.5:8100/build/vendor.js:11963:46)
at ComponentFactoryBoundToModule.create (http://192.168.0.5:8100/build/vendor.js:4715:29)
at c (http://192.168.0.5:8100/build/polyfills.js:3:19752)
at c (http://192.168.0.5:8100/build/polyfills.js:3:19461)
at http://192.168.0.5:8100/build/polyfills.js:3:20233
at t.invokeTask (http://192.168.0.5:8100/build/polyfills.js:3:15660)
at Object.onInvokeTask (http://192.168.0.5:8100/build/vendor.js:5436:33)
at t.invokeTask (http://192.168.0.5:8100/build/polyfills.js:3:15581)
at r.runTask (http://192.168.0.5:8100/build/polyfills.js:3:10834)
at o (http://192.168.0.5:8100/build/polyfills.js:3:7894)
at e.invokeTask [as invoke] (http://192.168.0.5:8100/build/polyfills.js:3:16823)
at p (http://192.168.0.5:8100/build/polyfills.js:2:27648)
统计.ts
@IonicPage()
@Component({
selector: 'page-stats',
templateUrl: 'stats.html',
})
export class StatsPage implements OnInit {
crops: Crop[];
crop = {} as Crop;
contracts: Contract[];
contract = {} as Contract;
stats = {} as Stats;
contentEle: any;
textEle: any;
@ViewChild('popoverContent', {read: ElementRef}) content: ElementRef;
@ViewChild('popoverText', {read: ElementRef}) text: ElementRef;
constructor(public navCtrl: NavController, private popoverCtrl: PopoverController,
private cropProvider: CropProvider,
private contractProvider: ContractProvider) {
console.log("Into the stats page........");
console.log("cropProvider: " + cropProvider);
console.log("contractProvider: " + contractProvider);
this.cropProvider.getAllCrops()
.then((crops: Crop[]) => {
this.crops = crops;
})
.catch(e => console.error(e));
this.contractProvider.getAllContracts()
.then((contracts: Contract[]) => {
this.contracts = contracts;
})
.catch(e => console.error(e));
this.buildStats();
}
buildStats() {
console.log("crops:" + this.crops);
console.log("contracts:" + this.contracts);
for (let crop of this.crops) {
this.stats.cropName = crop.cropName;
this.stats.grossMarketable = crop.acres * crop.expectedAPH;
this.stats.aphMarketable = crop.acres * crop.guaranteedAPH;
}
console.log("cropName: " + this.stats.cropName);
console.log("grossMarketable: " + this.stats.grossMarketable);
console.log("grossMarketable: " + this.stats.aphMarketable);
for (let contract of this.contracts) {
this.stats.amountSold = contract.contractTotalBushels;
this.stats.percentageGross = (this.stats.amountSold / this.stats.grossMarketable) * 100;
this.stats.percentageAPH = (this.stats.amountSold / this.stats.aphMarketable) * 100;
this.stats.avgSold = (this.contract.contract1Total + this.contract.contract2Total + this.contract.contract3Total) /
(this.contract.contract1Price + this.contract.contract2Price + this.contract.contract3Price);
}
console.log("amountSold: " + this.stats.amountSold);
console.log("percentageGross: " + this.stats.percentageGross);
console.log("percentageAPH: " + this.stats.percentageAPH);
console.log("avgSold: " + this.stats.avgSold);
console.log("stats: " + this.stats);
}
ngOnInit(): void {
console.log("Into the ngOnInit page........");
}
}
主页.html
<ion-tabs color="primary">
<ion-tab [root]="tab1Root" tabIcon="stats" tabTitle="Stats"></ion-tab>
<ion-tab [root]="tab2Root" tabIcon="calculator" tabTitle="Calculations"></ion-tab>
</ion-tabs>
主页.ts
@IonicPage()
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
tab1Root = StatsPage;
tab2Root = CalcPage;
}
控制台日志:
[app-scripts] [23:20:57] console.log: Into the stats page........
[app-scripts] [23:20:57] console.log: cropProvider: [object Object]
[app-scripts] [23:20:57] console.log: contractProvider: [object Object]
[app-scripts] [23:20:57] console.log: crops:undefined
[app-scripts] [23:20:57] console.log: contracts:undefined
不知道我在这里错过了什么。我已经在构造函数中注入了它们。
解决方案
您必须在其中填充一些值之前初始化crops
和的所有属性。contracts
因为,我不知道crops
. 我无法展示如何初始化所有数组属性。但是对于普通数组,下面的初始化将起作用。
this.crops = [];
this.contracts = [];
因此,您的代码将如下所示:
...
console.log("Into the stats page........");
console.log("cropProvider: " + cropProvider);
console.log("contractProvider: " + contractProvider);
this.crops = [];
this.contracts = [];
this.cropProvider.getAllCrops()
.then((crops: Crop[]) => {
this.crops = crops;
})
.catch(e => console.error(e));
...
仅供参考:在构造函数中有业务逻辑是不好的。
推荐阅读
- typescript - 如何更新深度嵌套的对象(类型缩小未按预期工作,keyof 编译错误)
- node.js - 与预设文件斗争 不允许导出对象,只有功能
- snowflake-cloud-data-platform - 如何在 Snowflake 中创建基于字段类型自动生成新表的计划任务?
- python-3.x - Deltalake Python 库无法安装在 Python 3.7 或 3.8 的 Amazon Linux 2 EC2 实例上
- android - 我应该使用 AsyncTask 来检索用户信息吗?
- python - 无法在 django 中导入文件
- reactjs - 第二次进入后的onChange效果
- android - 数据绑定:变量名的“未解析引用”
- reactjs - 如何在父项中设置状态而不触发 React 中子项的重新渲染?
- swift - 表视图中的搜索栏失败