0

Below are the Conversation & Message models I am using in my Ionic 5 / Angular app:

export class Conversation {
    constructor(
        public id: string,
        public userId: string,
        public mechanicId: string,
        public messages: Message[]
    ) { }
}

And here is the Message model:

export class Message {
    constructor(
        public id: string,
        public text: string,
        public userId: string,
        public timestamp: string
    ) { }
}

When a user creates a Conversation object, I want them to add 1 Message object within the Conversation.

Then when other uses are updating the Conversation (i.e. sending more messages), they will just be pushing another Message to the Conversation.

Here is what I have so far for creating a Conversation:

onSendMessage() {
    this.conversationService.addConversation(
        this.mechanicToContact.id,
        this.form.value.message
    );
}

I've tried the following method in my ConversationService:

addConversation(mechanicId: string, message: string) {
    const newConversation = new Conversation(
      Math.random().toString(),
      this.authService.userId,
      mechanicId,
      new Message(Math.random().toString(), message, this.authService.userId, mechanicId)
      );
  }

But I'm getting this error when trying to create the new Message:

Argument of type 'Message' is not assignable to type parameter of 'Message[]'

I'm not sure how I should pass the remaining attributes of the Message. Can someone please tell me how this is done?

2 Answers 2

1

Well, the class Conversation expects a Message[], which is an array of messages, and you are sending a Message. Couple ways to fix this. One being:

const newConversation = new Conversation(conversationId, userId, mechanicId, [ message ]);

This just wraps the message in an array.


Another one:

export class Conversation {
    public messages: Message[];

    constructor(
        public id: string,
        public userId: string,
        public mechanicId: string,
        messages: Message | Message[]
    ) { 
      this.messages = Array.isArray(messages) ? messages : [ messages ];
    }

    addMessages(messages: Message | Message[]): void {
       this.messages.push(
          ...(Array.isArray(messages) ? messages : [ messages ])
       );
    }
}

This will be able to accept both an array as a message object, and handles the correct way inside the class.


It's more common to have a service handle this. You can think of something like this:

export interface Conversation {
  id: string;
  userId: string;
  mechanicId: string;
  messages: Message[];
}

@Injectable({
  providedIn: 'root'
})
export class ConversationService {
  private conversations: Conversation[];

  addConversation(mechanicId: string, message: string): Conversation {
    const conversation: Conversation = {
      id: getUniqueUid() // something like this,
      userId: this.userService.getUserId() // something like this
      mechanicId,
      messages: [ this.createMessage(message) ] 
    };

    this.conversations.push(conversation);

    return conversation;
  }

  addToConversation(id: string, mechanicId: string, message: string): Conversation {
    const conversation = this.getConversation(id);

    if (conversation) {
      conversation.messages.push(
        this.createMessage(message)
      );
    }

    return conversation;
  }

  private createMessage(message: string): Message {
    return {
      id: getUniqueMid() // something like this,
      text: message,
      userId: this.userService.getUserId(),
      timestamp: Date.now()
    };
  }

  private getConversation(id: string): Conversation | undefined {
    return this.conversations.find((conversation) => conversation.id === id); 
  }
}
Sign up to request clarification or add additional context in comments.

15 Comments

A quick question: why declare type messages: Message | Message[] when it'll always be assigned an array of Message? Wouldn't messages: Message[] suffice?
@MichaelD the constructor is how you call it with new, if you declare it like this, you can call it with Message and Message[]. However the public class property messages is of type Message[]. You can see that declared above the constructor. The constructor parameter messages is not the same as this.messages of the class
When creating the Conversation initially, I will only be passing one message. Also, when updating the Conversation (i.e. sending a message back), I will still only be passing one message. Does your solution provide for this?
@user9847788 this solution provides for allowing a single message object as constructor parameter of your Conversation class. The updating of a conversation should probably use a push on the this.messages(), but you did not show that piece of code
@user9847788 I've added a addMessages method
|
0

Your addConversation function should be this

addConversation(userId: string, mechanicId: string, messages: Message[]) {
    const newConversation = new Conversation(conversationId, userId, mechanicId, messages);
  }

You use an array in your conversation class, but only give it one message as a parameter.

Comments

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.