Reputation: 797
I make following request in Angular and save the response in a variable:
conversations: Conversation[];
// ChatService
getConversations() {
return this.http.get<Conversation[]>('/chat/conversations');
}
this.chatService.getConversations().subscribe(
(response: Conversation[]) => this.conversations = response
);
This is the JSON Data from the Server:
[
{
"chatRoomId":"096b8be1-2411-4cb1-94e0-ed96c51c23d8",
"name":"Bar",
"profilePicture":"...",
"conversation":[
{
"name":"Bar",
"message":"Hello!",
"createdAt":"2018-09-30T06:50:49.000+0000"
},
{
"name":"Foo",
"message":"Hi",
"createdAt":"2018-09-30T11:49:05.000+0000"
}
]
}
]
TypeScript Models:
export interface Conversation {
chatRoomId: string;
name: string;
profilePicture: string;
conversation: ChatMessage[]
}
export interface ChatMessage {
name: string;
message: string;
createdAt: string;
}
The problem:
If i output the variable in the console, the conversation (conversation: ChatMessage[]
) is an empty array element.
And if i make the request with this.http.get<any>('...')
, the conversation get's stored as expected.
Upvotes: 2
Views: 725
Reputation: 892
There's a few ways you can do what you're trying to do but from my experience, using this library has been the easiest: https://github.com/typestack/class-transformer
Here's how it would work in your situation. First I would change your interfaces to be Typescript Classes.
import { Type } from 'class-transformer';
export class Conversation {
chatRoomId: string;
name: string;
profilePicture: string;
@Type(() => ChatMessage)
conversation: ChatMessage[]
constructor(args: Conversation) {
Object.assign(this, args);
}
}
export class ChatMessage {
name: string;
message: string;
createdAt: string;
constructor(args: ChatMessage) {
Object.assign(this, args);
}
}
A few things changed from when these were interfaces::
@Type
decorator comes from the class-transformer module. This allows you to transform nested objects. Here is the documentation: https://github.com/typestack/class-transformer#working-with-nested-objectsconstructor
which allows you to create instances of these Classes and pass through attributes to them of their own respective types. Take a look at this post Converting httpClient answer to model objects [Angular 6] as it shines more light onto whats happening here.Then within your service this is how your code changes:
import { plainToClass } from 'class-transformer';
conversations: Conversation[];
// ChatService
getConversations() {
return this.http.get<Conversation[]>('/chat/conversations');
}
this.chatService.getConversations().subscribe(
(response: Conversation[]) => {
this.conversations = plainToClass(Conversation, response) as Conversation[]
}
);
plainToClass
will take the raw JSON response and transform it into instances of your Conversation Class. If you console.log out this.conversations
you will see that it returns an Array of Conversations that each have an array attribute called conversations
of type ChatMessage.
Upvotes: 1