I am new to API's and Angular and I'm running into an issue I can't seem to resolve.
For a project I am currently working on I have set up a simple Rails API with the fast_jsonapi. This formats my JSON responses to be in line with JSON:API. I then have an Angular app which should take in that response and map it with the Angular2-jsonapi module. For this issue imagine we have roles and accountabilities. One role can has 0 to many accountabilities. An accountability belongs to a single role. When I sent a request to return all the roles, I get a JSON response which then gets properly mapped to models by the module. The issue arises when I try to include relationships.
According to the readme I have to define which relationship to include in the .findAll method like so:
{ include: 'accountabilities' }
The correct data is requested from the rails API, as it is the same request which I tested with Postman earlier. However the error that appears in my browser console is as follows:
{message: "parseHasMany - Model type for relationship accountability not found."}
I have tried other relationships and went through the setup proces a couple of times now, but I fail to see where things are going wrong. Searches on Google, Github and Stackoverflow haven't helped me in this case. Any help is very much appreciated.
Here is the relevant code. If any other information or code is needed, let me know and I'll happily update this post.
Example JSON response:
{
"data": [
{
"id": "1",
"type": "role",
"attributes": {
"name": "Farming Engineer",
"purpose": "Iure voluptatum rem dolores.",
"created_at": "2020-01-16T18:38:26.151Z",
"updated_at": "2020-01-16T18:38:26.151Z"
},
"relationships": {
"accountabilities": {
"data": [
{
"id": "6",
"type": "accountability"
},
{
"id": "12",
"type": "accountability"
}
]
}
}
},
{
"id": "2",
"type": "role",
"attributes": {
"name": "IT Supervisor",
"purpose": "Iusto fuga fugiat qui.",
"created_at": "2020-01-16T18:38:26.161Z",
"updated_at": "2020-01-16T18:38:26.161Z"
},
"relationships": {
"accountabilities": {
"data": []
}
}
}
],
"included": [
{
"id": "6",
"type": "accountability",
"attributes": {
"description": "penetrate the market",
"created_at": "2020-01-16T18:38:26.480Z",
"updated_at": "2020-01-16T18:38:26.480Z"
},
"relationships": {
"role": {
"data": {
"id": "1",
"type": "role"
}
}
}
},
{
"id": "12",
"type": "accountability",
"attributes": {
"description": "immersive experience",
"created_at": "2020-01-16T18:38:26.507Z",
"updated_at": "2020-01-16T18:38:26.507Z"
},
"relationships": {
"role": {
"data": {
"id": "1",
"type": "role"
}
}
}
}
]
}
role.model.ts
import {
JsonApiModelConfig,
JsonApiModel,
Attribute,
HasMany,
BelongsTo
} from 'angular2-jsonapi';
import { Accountability } from '@app/shared/models/accountability.model';
@JsonApiModelConfig({
type: 'roles'
})
export class Role extends JsonApiModel {
@Attribute()
name: string;
@Attribute()
purpose: string;
@Attribute({ serializedName: 'created_at' })
createdAt: Date;
@Attribute({ serializedName: 'updated_at' })
updatedAt: Date;
@HasMany()
accountabilities: Accountability[];
}
accountability.model.ts
import {
JsonApiModelConfig,
JsonApiModel,
Attribute,
BelongsTo
} from 'angular2-jsonapi';
import { Role } from '@app/shared/models/role.model';
@JsonApiModelConfig({
type: 'accountabilities'
})
export class Accountability extends JsonApiModel {
@Attribute()
description: string;
@Attribute({ serializedName: 'created_at' })
createdAt: Date;
@Attribute({ serializedName: 'updated_at' })
updatedAt: Date;
@BelongsTo()
role: Role;
}
datastore.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {
JsonApiDatastoreConfig,
JsonApiDatastore,
DatastoreConfig
} from 'angular2-jsonapi';
import { Role } from '@app/shared/models/role.model';
import { Accountability } from '@app/shared/models/accountability.model';
const config: DatastoreConfig = {
baseUrl: 'http://localhost:3000/api',
apiVersion: 'v1',
models: {
roles: Role,
accountabilities: Accountability
}
};
@Injectable()
@JsonApiDatastoreConfig(config)
export class Datastore extends JsonApiDatastore {
constructor(http: HttpClient) {
super(http);
}
}
role.component.ts
import { Component, OnInit } from '@angular/core';
import { Datastore } from '@app/datastore';
import { Role } from '@app/shared/models/role.model';
import { JsonApiQueryData } from "angular2-jsonapi";
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.sass']
})
export class HomeComponent implements OnInit {
roles: Role[];
constructor(private datastore: Datastore) { }
ngOnInit() {
this.datastore
.findAll(Role, { include: 'accountabilities' })
.subscribe((roles: JsonApiQueryData<Role>) => {
console.log('>>>>>>>>>>>>>', roles);
console.log('>>>>>>>>>>>>>', roles.getModels());
this.roles = roles.getModels();
});
}
}
With a lot of help over on this Github topic I finally managed to get this resolved.
What initially caused the issue is that the response that I got from my API listed the type
in relationships
and included
in singular whereas they needed to be plural.
Adding record_type: :accountabilities
to the has_many
relationship in my serializer changed this and successfully mapped the response to objects.