使用ngOnInit()中的数据绑定从本地JSON文件中读取数据会导致未定义的变量

时间:2017-12-05 17:32:49

标签: json angular typescript parsing

我正在尝试从assets文件夹中的json文件中获取数据,然后将此数据分配给将绑定到子组件的另一个@Input变量的变量。

  • 代码

基于网络上的多个解决方案,我以这种方式检索我的JSON数据:

@Injectable()
export class JSONService {

    constructor(private http: HttpClient) { }

    public fromJSON(jsonFileName: string): Observable<any[]> {
      let result: any[] = new Array();
      let pathToJson: string = "assets/" + jsonFileName + ".json";

      return this.http.get(pathToJson).map(data => {
        let result: any[] = new Array();
        // Apply some treatment on data and push it to the result array
        return result;
      });
    }
}

然后我在父组件的ngOnInit()方法中调用我的服务:

ngOnInit() {
    this.jsonService.fromJSON("users.json").subscribe(fields => {
      this.fields= fields;
      console.log(this.fields); // Log (I): this.fields is well defined
    });
    console.log(this.fields); // Log (II): this.fields is undefined
}

将变量fields绑定到子组件的位置:

<child-component [childFields] = "fields"></child-component>
  • 问题

我面临的问题是对fromJSON方法的异步调用导致this.fields在页面执行生命周期的某个时刻(Log (II)从代码中未定义)上面),这导致将this.fields变量的未定义值发送到子组件。

如何避免使用fields变量的未定义值,并确保子组件始终使用json文件中的数据加载?

3 个答案:

答案 0 :(得分:1)

只需添加* ngIf即可检查数据是否已加载

<child-component *ngIf="fields" [childFields] = "fields"></child-component>

答案 1 :(得分:1)

Service.ts

@Injectable()
export class JSONService {

    constructor(private http: HttpClient) { }

    public fromJSON(jsonFileName): Observable<any[]> {
      console.warn('Retriving Default Data from File.......');
    return this.http.get(filename)
      .map(this.extractData)
      .catch(this.handleError);
    }
  private extractData(res: Response) {
    let body = res.json();
    return body || [];
  }

  private handleError(error: any) {
        const errMsg = (error.message) ? error.message :
          error.status ? `${error.status} - ${error.statusText}` : 'Server error';
        console.error(errMsg);
        console.log('Server Error!');
        return Observable.throw(errMsg);
      }
}

parent.component.ts

constructor(public jsonService: jsonService) {
  }

  ngOnInit() {

          this.jsonService.fromJSON('assets/users.json').subscribe(
          function (success) {
            this.data = success;
           this.datahandle(success);
          },
          error => console.log('Getting Server Data Error :: ' + 
    JSON.stringify(error)));

}
datahandle(jsonData){

console.log('check data' + JSON.stringify(jsonData)); <-----check data

// may parse your jsonData  if required
this.fields = jsonData ;

let keys = Object.keys(jsonData);
console.log(keys);


}
}

parent.component.html

<child-component *ngIf="fields" [childFields] = "fields"></child-component>

答案 2 :(得分:0)

假设您的组件有点像下面

export class SomeComponent implements OnInit {
  public fields: any[];

  ngOnInit() {
    this.jsonService.fromJSON("users.json").subscribe(fields => {
      this.fields = fields;
      console.log(this.fields); // Log (I): this.fields is well defined
    });
    console.log(this.fields); // Log (II): this.fields is undefined
  }
}

然后,您可以使用空数组

初始化字段
public fields: any[] = [];

模板中的OR

<child-component *ngIf="fields" [childFields]="fields"></child-component>