Previous page: Create and POST a new message using a GraphQL Mutation
Send Data with Angular Form Components
Create an Angular component to send a message to the GraphQL API
Our GraphQL mutation is ready for client integration. We can now build the user interface to send an anonymous user message to our GraphQL API, which will forward the request on to the Slack API. We will then be able to see new message(s) created by our Angular app on refresh of our application in the browser.
Before we can start using forms in Angular, we need to import the
FormsModule
into our application. From your project folder, open the file
web-app/src/app/messages.module
, then import and add the module.

// Exisitng import code...
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [
// Existing code...
],
imports: [
CommonModule,
FormsModule, // <-- Add new module here
MessagesRoutingModule
]
})
export class MessagesModule {}
Note: The order of imports is important.
Create the text field Angular component
We'll first look at the Typescript component we'll use to send a message.
Primarily we'll need to import Apollo to get an instance of the Apollo client
from our constructor. Then create a sendMessage
method responsible for
creating a GraphQL mutation query to be sent to our API.
From your project folder, open the
web-app/src/app/messages/create-message/create-message.component.ts
file
and add the following code:

import { Component, OnInit } from '@angular/core';
import { Apollo } from 'apollo-angular';
import gql from 'graphql-tag';
import conversationMessageFragment from '../shared/conversation-message-fragment.gql';
@Component({
selector: 'app-messages-create-message',
templateUrl: './create-message.component.html',
styleUrls: ['./create-message.component.scss']
})
export class CreateMessageComponent implements OnInit {
text: String = '';
constructor(private apollo: Apollo) { }
ngOnInit() {}
sendMessage() {
if (!this.text) {
return false;
}
const textCache = this.text;
this.text = '';
this.apollo
.mutate({
mutation: gql`
mutation createMessage {
createMessage(text: "${textCache.replace('\n', '')}") {
...conversationMessage
}
}
${conversationMessageFragment}
`
})
.subscribe();
}
}
The structure of this component should look familiar. After the imports, we have
metadata in the Component
decorator to describe the location of compile-time
assets and the selector
name. At the top of the class
CreateMessageComponent
we define the text
string property, which will be
the model of the input text field and hold the value of the user-typed message.
The constructor gives us the instance of our Apollo client. We don't need the
ngOnInit
method but it's automatically generated by the CLI and have left
it in.
The sendMessage
method is called when a user indicates that they've
finished typing and want to send the message. The method has a guard that
stops an empty message getting sent. If a message isn't empty, it will cache the
message and instantly reset the text field whilst the message is being sent.
Finally we make a call to the GraphQL API with the gql
mutation query
in the request body (through an observable subscription). This defines the
mutation createMessage
with a text
argument that is supplied with a
tidied string. Lastly a fragment that we previously used to define a message
body in the request is reused here with ...conversationMessage
.
Create the HTML template for writing a message
We have the behaviour of our component all ready to go, lets now create the layout of our text field and bind it to our component.
From the same folder, open the file: create-message.component.html
and
replace the contents with the following code.

<div class="messages-create-message">
<textarea class="messages-create-message__input"
[(ngModel)]="text"
(keyup.enter)="sendMessage()"></textarea>
<button class="messages-create-message__send" (click)="sendMessage()">Send message</button>
</div>
Again, we've used BEM to style the component and determine our class
structure. And also added a textarea
form control that is bound to the
Typescript components text
property with the syntax [(ngModel)]="text"
.
Notice the use of both square brackets and parentheses [()]
to wrap
ngModel
. This indicates
two-way model binding
within the component so that not only will the components text
property get
updated when the user types in the text field but the words typed in the
textarea
can also be updated as a result of the components behaviour. This
allows the code this.text = '';
within the sendMessage
method to delete all
the words that a user has entered so they can start typing a new message.
We use
event binding
(keyup.enter)="sendMessage()"
, which will call
the sendMessage
method when a user hits the
'enter' key.
As well as typing 'enter', a user can also click the 'Send message' button
,
which will call the same method through a click
event binding.
Create the styles for the text field and button
To complete our component, we just need to add the styles. Within the same
folder, Open the file create-message.component.scss
and add the following:

.messages-create-message {
padding : .5rem .5rem 1rem .5rem;
background-color : #f5f5f5;
* {
box-sizing: border-box;
font-size : 1rem;
font-family: 'Helvetica Neue', Arial;
}
&__input {
min-height : 5rem;
width : 100%;
padding : .6rem;
border-radius : 5px;
border : 1px solid #999;
&:focus,
&:active {
border-color : #004586;
outline : none;
box-shadow: 0 0 0 3px #0385ff;
}
}
&__send {
margin-top : .5rem;
padding : .6rem 1rem;
font-size : 1.2rem;
font-weight : normal;
color : #fff;
background-color : #0099ff;
border : none;
border-radius : 3px;
cursor : pointer;
}
}
That's everything we need to send a message from the application!
Navigate to the Angular application in your browser, type a message in the new component and send. When you refresh the page, you should see your messages at the bottom of the list. It will also appear in systems notifications that have been enabled from any downloaded Slack apps you might have installed for your laptop or mobile phone when logged in to the same Slack workspace.
Note: The application is setup to show a maximum of 4 messages at a time.
This can be changed within the max
variable of the query defined in the
view-conversation.component.ts
component.
At the moment we have to refresh the browser window in order to see new messages that we or anyone else created, lets fix that by using a subscription.
Next, create a GraphQL Subscription to update the Angular app in real time
Previous page: Create and POST a new message using a GraphQL Mutation