I'm trying to learn how to get content from Drupal 8 into my Angular 7 app using jsonapi, starting from Preston So's book, Decoupled Drupal in Practice. It stops short of showing how to get resources from relationships and included.
The jsonapi spec offers an include function where I can get related resources from a node without having to make a separate call.
Using http://localhost/jsonapi/node/article/MYUUID?include=field_image presents a nice json object in this general format.
jsonapi
data
--attributes
--relationships
included
I'm trying to get the included portion but my ArticleService is only getting the contents of the data, and I want to get the included as well.
My article.ts
export class Article {
attributes: object;
relationships: object;
included: object;
}
My article.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { Article } from '../articles/article';
import { Image } from '../articles/image';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'})
}
@Injectable({
providedIn: 'root'
})
export class ArticleService {
private articlesUrl = 'http://localhost/jsonapi/node/article';
constructor(private http: HttpClient) {}
getArticle(id: string): Observable<Article>
{
if (id) {
return this.http.get<Article>(this.articlesUrl + '/' + id + '?include=field_image', httpOptions)
.pipe(
map(res => res['data'])
)
.pipe(
catchError(this.handleError([]))
);
}
}
private handleError<T> (result?: T) {
return (error: any): Observable<T> => {
console.error(error);
return of(result as T);
}
}
}
So my first map function is retrieving the data object from the body. I should be able to enlarge that. I attempted setting
map(res => res['body'])
, then map(res => res[''])
which returns no object. Reading up on the rxjs/operators I see some operators like mergeMap, concatMap which fail because I'm not understanding how to get the content of the entire body of the response. My searches have yielded little that seems to help, so I'm looking for pointers on how to get the entire body of the response.
article.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { Article } from '../articles/article';
import { Image } from '../articles/image';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'})
}
@Injectable({
providedIn: 'root'
})
export class ArticleService {
private articlesUrl = 'http://localhost/jsonapi/node/article';
constructor(private http: HttpClient) {}
getArticle(id: string): Observable<Article>
{
if (id) {
return this.http.get<Article>(this.articlesUrl + '/' + id + '?include=field_image', httpOptions);
}
}
private handleError<T> (result?: T) {
return (error: any): Observable<T> => {
console.error(error);
return of(result as T);
}
}
}
component.ts
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ArticleService } from './article.service'; // import ArticleService service from article.service.ts file
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
// inject ArticleService to the component
constructor(private articleService : ArticleService ) {
this.getArticle(); call getArticle function onInit
}
getArticle() {
const id = 12; // getting article id 12 details
// subscribe to getArticle service method will call HTTP request and return response
this.articleService.getArticle(id).subscribe((response)=> {
// on successful request this block get called
console.log('response body');
console.log(response);
console.log('response actual data');
console.log(response.body);
}, (error)=> {
// on error this block get called like 404, 500 http status
})
}
}