Angular 8读取外部JSON转字符串数组填充JExcel Grid遇undefined问题
解决Angular中JExcel Grid加载外部JSON数据返回undefined及数据转换问题
我来帮你搞定这个问题,你遇到的rowdata返回undefined的核心原因是异步操作的时机问题——你在调用服务后立刻打印rowdata,但此时Promise还没完成,数据还没加载进来。另外还需要把JSON数据转换成JExcel要求的二维字符串数组格式。下面是完整的修复方案和实现流程:
一、先明确问题根源
- 异步时序错误:
getvaluefromjson()是异步操作,你在ngOnInit里调用then后立刻console.log(this.rowdata),此时Promise还未resolve,所以rowdata还是初始的undefined。 - 数据格式不匹配:JExcel需要的是二维数组(每个子数组对应一行的单元格数据),但你直接把JSON返回的对象数组丢给它,格式不兼容。
- JExcel初始化时机:原来的代码在
ngAfterViewInit里直接初始化表格,但此时数据还没加载,导致表格无法显示数据。
二、完整代码实现
1. 修正User接口(明确类型)
export interface User { value: string; // 去掉可选符,明确类型为string,和JSON结构匹配 }
2. 优化GetjsonService(改用Observable,更符合Angular最佳实践)
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { User } from '../assets/user'; // 注意路径要和你的项目结构匹配 @Injectable({ providedIn: 'root' }) export class GetjsonService { constructor(private http: HttpClient) { console.log("json service called"); } // 返回Observable类型,替代Promise,更适合Angular异步场景 getvaluefromjson(): Observable<User[]> { return this.http.get<User[]>('assets/user.json'); } }
3. 修复StaticdataComponent(处理异步时序+转换数据格式)
import { Component, OnInit, AfterViewInit } from '@angular/core'; import * as jexcel from 'jexcel'; import { FormControl } from '@angular/forms'; import { GetjsonService } from 'src/service/getjson.service'; import { User } from 'src/assets/user'; @Component({ selector: 'app-staticdata', templateUrl: './staticdata.component.html', styleUrls: ['./staticdata.component.css'] }) export class StaticdataComponent implements OnInit, AfterViewInit { rowdata: User[] = []; spreadsheetInstance: any; // 保存JExcel实例,方便后续更新数据 constructor(private jsonservice: GetjsonService) {} ngOnInit(): void { // 使用subscribe监听数据加载完成事件 this.jsonservice.getvaluefromjson().subscribe({ next: (data) => { this.rowdata = data; console.log("Row data:", this.rowdata); // 数据加载完成后,更新表格内容 this.updateJExcelData(); }, error: (err) => { console.error('加载JSON数据失败:', err); } }); } ngAfterViewInit() { // 先初始化空表格,等数据加载后再填充 this.spreadsheetInstance = jexcel(document.getElementById("spreadsheet"), { columns: [ { title: 'Value', type: 'text', width: '300px' }, ], minDimensions: [1, 0], // 初始0行,避免多余空行 contextMenu: () => null, // 简化箭头函数写法 }); } // 转换数据格式并更新JExcel updateJExcelData() { if (!this.spreadsheetInstance || !this.rowdata.length) return; // 把User对象数组转换成JExcel需要的二维字符串数组 const formattedRows = this.rowdata.map(user => [user.value]); // 更新表格数据 this.spreadsheetInstance.setData(formattedRows); } selectedasset: String; asset = new FormControl(); assetlist: string[] = ['Number of screens', 'Processing capacity above 8 GB ram', 'WFH Option', 'All Applications Whitelisted', 'Ethernet Cable', 'Stable Broadband connection']; // Adding a row on Grid gridrowadd() {} }
4. 别忘了在AppModule中导入HttpClientModule
确保你的app.module.ts里已经导入了HttpClientModule,否则HttpClient无法使用:
import { HttpClientModule } from '@angular/common/http'; @NgModule({ imports: [ // ...其他已导入的模块 HttpClientModule ] }) export class AppModule { }
三、关键修复说明
- 异步时序处理:通过
subscribe监听数据加载完成事件,确保只有在数据真正返回后才更新rowdata和表格内容。 - 数据格式转换:用
map方法把每个User对象转换成包含value的数组,匹配JExcel要求的二维数组格式。 - JExcel实例管理:保存表格实例,在数据加载完成后调用
setData方法更新内容,避免初始化时数据未就绪的问题。
内容的提问来源于stack exchange,提问作者Aashiq
相关产品推荐
相关产品推荐

