0

I am trying to query the wagtail API that will return JSON in a very unfriendly format.

{
    "id": 3,
    "meta": {
        "type": "home.HomePage",
        "detail_url": "http://localhost:8000/api/v1/pages/3/"
    },
    "parent": null,
    "title": "Homepage",
    "body": "<h2>cool an h2 fgf</h2>",
    "main_image": {
        "id": 1,
        "meta": {
            "type": "wagtailimages.Image",
            "detail_url": "http://localhost:8000/api/v1/images/1/"
        }
    },
    "header_image": {
        "id": 1,
        "meta": {
            "type": "wagtailimages.Image",
            "detail_url": "http://localhost:8000/api/v1/images/1/"
        }
    },
    "show_in_menus": true,
    "full_url": "/media/images/Background-4.original.jpg"
}

All I really want from that is a class like this.

export class HomePage {
  id: number;
  title: string;
  body: string;
  full_url: string;

}

But whenever I get back from the data back from my service and try and log it, it is undefined.

Is there any way for me to ignore the fields I don't want from a JSON in typescript?

The service I am using is:

import { Injectable } from '@angular/core';
import {Http, Response} from '@angular/http';
import {Observable} from "rxjs";
import {HomePage} from "./HomePage";

@Injectable()
export class HomePageService {

  constructor(private http: Http){
  }

  getHomePage(GUID: number): Observable<HomePage>{
    return this.http
      .get("http://localhost:8000/api/v1/pages/" + GUID + "/")
      .map(this.extractData)
      .catch(this.handleError);
  }
  private extractData(res: Response) {
    let body = res.json();
    return body.data || {}
  }
  private handleError (error: Response | any) {
    // In a real world app, we might use a remote logging infrastructure
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }
}

And the component:

import {Component, OnInit, OnDestroy} from '@angular/core';
import {HomePageService} from './home-page.service';
import {ActivatedRoute} from '@angular/router';
import {HomePage} from "./HomePage";

@Component({
  selector: 'app-home-page',
  templateUrl: './home-page.component.html',
  styleUrls: ['./home-page.component.css'],
  providers: [HomePageService]
})
export class HomePageComponent implements OnInit, OnDestroy{
  id: number;
  private sub: any;
  public homePage: HomePage;
  errorMessage: string;
  constructor(private homePageService : HomePageService, private route: ActivatedRoute) {

  }

  ngOnInit() {
    this.sub = this.route.params.subscribe(params => {
      this.id = +params['id'];
    });
    this.homePageService.getHomePage(this.id)
      .subscribe(
        homePage => this.homePage = new HomePage(homePage),
        error =>  this.errorMessage = <any>error,
        () => console.log(this.homePage.full_url)
      );
    console.log(this.id);
  }
  ngOnDestroy() {
    this.sub.unsubscribe();
  }

}
3
  • could you add code for the service that is getting the data? Commented Feb 27, 2017 at 10:11
  • Added the component and the service code, thanks. Commented Feb 27, 2017 at 10:32
  • homePage => this.homePage = new HomePage(homePage) - do you have a constructor for HomePage class? Commented Feb 27, 2017 at 11:26

1 Answer 1

1

homePage => this.homePage = new HomePage(homePage) - in your code I don't see a constructor defined for HomePage class. So when you pass the homePage object to it, nothing happens. Try this:

export class HomePage{
    id: number;
  title: string;
  body: string;
  full_url: string;

  constructor(homePageObj: any)
  {
      if (homePageObj)
      {
          this.id = homePageObj.id;
          this.title = homePageObj.title;
          this.body = homePageObj.body;
          this.full_url = homePageObj.full_url;
      }
  }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Hi, thanks for that, but it didn't work. homePageObj is not populated with anything. honestly, I thought the constructors auto-populate when you define class variables as in the Heroes example they don't fill the constructor like this.
There was actually an issue with the service here. return body.data || {} needed to be return body || {} I just copied that code from somewhere badly. I believe that this answers the question I asked, though. As when the parameters don't match the response body correctly you will need angular will throw an error and you should define constructor manually. Thank you
Another thing you can try is return <HomePage>body.data || {}.
Thanks that will mean I don't have to instantiate the object in the component =)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.