简体   繁体   中英

Angular 2 - Using/displaying JSON data fetched through HTTP, or mocked

I'm working on an Angular 2 application, and I'm trying to use JSON data, either local/mocked or fetched via HTTP, and display it on a component. I have an injectable service that will do the fetching/mocking -

import { Injectable } from 'angular2/core';

@Injectable()
export class TestService {
  testString:string = "";
  testDetails: string = "";

  constructor() { }

  getTestDetails(): Promise<string> {
    this.testDetails = {
      "status": "success",
      "message": "Data save successful",
      "data": {
        "Random_Data_1": "Random Data 1",
        "Random_Data_2": "Random Data 2"
      }
    };
    return Promise.resolve(JSON.stringify(this.propertyDetails));
  }
}

And then I have a component that uses the service via Dependency Injection -

import { Component, OnInit } from 'angular2/core';
import {TestService} from "./test.service";

@Component({
  selector: 'test',
  templateUrl: './test.component.html',
  styleUrls: []
})
export class TestComponent implements OnInit {
  testDetails: string = "";

  constructor(private testService: TestService) { }

  ngOnInit() {
    this.display();
  }

  display(): void {
    this.testService.getTestDetails()
      .then(
        testDetails => {
          this.testDetails = JSON.parse(testDetails);
        },
        errorMessage => {
          console.error("Something failed trying to get test details");
          console.error(errorMessage);
        }
      );
  }
}

The component HTML -

<div class="content">
  <p> Test Details </p>
  <p> {{ testDetails.data.Random_Data_1 }} </p>
</div>

The problem is, the HTML is erroring out trying to display the items in the testDetails JSON. I initially used it with md-tabs, so the first try would error out, but the other tabs would read the data fine. Also, the ngOnInit would be called twice when the error occurs. I have narrowed it down to the data coming in and the object types that is causing me the headache.

I know I can create a Details class and declare testDetails of type Details, and then map the JSON data into the class, but the thing is, I want to work with generic data, and only know a few components that will be present in the data. Is there a way to read the JSON, and use the data without having to define a separate class for each scenario ?

I have a plunker with the most basic stuff set up. The actual setup runs fine on my local system up until where I try to access the JSON data in the HTML, at which point the browser throws a cryptic error. The skeleton code doesn't even run on Plunker. That said, the structure in the Plunker defines the structure of my app and the data flow. Plunker with the basic setup

What is the best way to achieve this ? What is the standard/best practice to do this ?

Use

<p *ngIF="testDetails.data.Random_Data_1 "> {{ testDetails.data.Random_Data_1 }} </p>

This is because there is no data initially.Hope this helps you.

Throwing another option out there, since you asked about best way to achieve this . Might not be the best idea, this is subjective ;) But if I were you...

Thinking about the future, where you will use real backend, it could be nice to use mock json file. If/when you move over to a real backend, you wouldn't basically need to change anything else but the url of the requests :)

So I set up a simple example for you. Here I used Observables, but you can use Promises if you prefer that. Here's more info on HTTP if you want/need to read up on that. Most important thing is that you have the HttpModule imported in your app module.

You have your file with JSON and in your service make http-requests to that:

getTestDetails() {
  return this.http.get('src/data.json')
    .map(res => res.json())
}

Your display-method:

display() {
  this.testService.getTestDetails()
    .subscribe(data => {
      this.testDetails = data;
    });
}

And in the template use the safe navigation operator to safeguard null/undefined values:

<div class="content">
  <p> Test Details </p>
  <p> {{ testDetails?.data?.Random_Data_1 }} </p>
</div>

Here's a

Demo

As said, this is to give another approach on how to implement the things you want to achieve, and this would probably be my preferred way :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM