Reputation: 297
I'm creating a chatbot in angular 4 and I'm struggling a bit on how to display the messages properly. On enter I simply parse the value which is sent for computation, and at the same time stored into an array userMessage. When I get the response from the bot, I store that into another array called botMessage. Assuming I sent 3 messages this is how the output will display:
The output that I want to display is the one of a normal chat so it would be:
This is my html code
<ul >
<li class="bubble user-message" *ngFor = "let message of userMessage ">
{{message}}
</li>
<li class ="bubble bot-message" *ngFor = "let message of botMessage">
{{message}}
</li>
</ul>
Any suggestions? Thank you very much
edit this is my typescript code:
inputField
//this is called when enter is pressed. apiCall would be the service
onEnter(value: string) {
this.value = value;
this.userMessage.push(value);
this.apiCall.postValue(value this.output );
this.botMessage = this.apiCall.getMessages();
this.chat.displayMessages();
} //on enter
this is my service
private messages = [];
postValue(value:string, output:any){
this.http.post('/APIconversation', {"input":value})
.map(response=>response.json())
.subscribe(
data => {
// Read the result field from the JSON response.
output = data.text;
this.messages.push(output);
}
)
}
getMessages(){
return this.messages;
}
this is where I parse the arrays to the html to be rendered
@Input() userMessage: InputFieldComponent; //gets the array userMessage from the parent (input-field)
@Input() botMessage: InputFieldComponent; //gets the array botMessage from the parent (input-field)
displayMessages() {
this.messages = this.apiCall.getMessages();
}
Upvotes: 0
Views: 953
Reputation: 3718
updated answer
I recommend to store your bot-messages in an dictionary, with the key of the user-message like this:
botMessage = {};
userMessage = [];
onEnter(value: string) {
this.userMessage.push(value);
var context = this.apiCall.getContext(value);
this.apiCall.postValue(value, context, this.output);
const botMessages = this.apiCall.getMessages();
// Add all bot messages depending on their user messages
for(const message of botMessages) {
this.botMessage[message.userMessageId] = message;
}
}
Implied, that your bot-message has the info to which user-message it depends. With this structure, you can easily access the answer in your html like this:
<ul>
<li class="bubble" *ngFor="let message of userMessage">
<div class="user-message>{{ message }}</div>
<div *ngIf="botMessage[message.id]" class="bot-message>
{{ botMessage[message.id] }}
</div>
</li>
</ul>
Also I'm pretty sure, you have some asynchronous problems, but that's another chapter :-)
Upvotes: 2
Reputation: 6383
Keeping your data model, you could use an index:
<ul *ngFor = "let message of userMessage; let i=index;">
<li>
{{ message }}
</li>
<li> {{ botMessage[i] }} </li>
</ul>
Then adjust where to place the *ngFor.
The result is the one you would expect.
You would though need to check for lengths as they might be different between arrays, I'd recommend evaluating your data model.
Upvotes: 0
Reputation: 222522
You could merge these arrays into one and use a condition to check the bot and user based on a object property, you can't achieve with two arrays,
<div *ngFor="let message of Messages"
<div *ngIf="message.type === 'User'">
<user-message-item [message]="message"></sender-message-item>
</div>
<div *ngIf="message.type === 'Bot'">
<bot-message-item [message]="message"></receiver-message-item>
</div>
</div>
Upvotes: 0