Create a Chat Interface With NativeScript
This article is a step by step guide for creating a Chat Component using Angular2 and NativeScript. You can find the complete source code on GitHub.
I’ll consider that NativeScript and its dependencies have already be set up and configured on your machine. If it’s not the case, you can follow the official guide available here.
Start by creating the app, running:
Prepare the Data
Let’s now prepare the data model. We’ll need the following:
- the information of the current user, or ‘me’. It should have a name, and a mini profile picture that will be displayed along with each message.
- The information of the other user, or ‘other’. Also has a profile picture but also a cover that will be displayed on top of the screen.
- A list of messages, written either by ‘me’ or ‘other’. Each message has a content text, as well as a date.
As these data will be pretty specific to your application, we will work with fake ones. Let’s implement a ChatService that will provide us with some fake data. I’m going to use the faker library for this, so install it as a dependency first:
Let’s also add some interfaces in order to structure the data a little bit. This will improve the readability of the service and help us identify quickly what we will need for the future, real implementation:
Now we can implement our fake
ChatService by making use of the previously declared Chat interface:
The goal of this service is to come up with a
Chat object populated with some random data, and 4 messages. These will be distributed randomly between ‘me’ and ‘other’. Before returning the list of messages, we sort them by their date for the actual stream to make sense. Notice also the use of the https://unsplash.it image service. it enables us to retrieve images identified by the given id, and with the given size. Feel free to visit the website and choose whatever image id’s you want for your application.
And example of call from ChatService.getChat() will be:
Create the Chat Component
The main Component will be the
ChatComponent, which will host the conversation interface and make use of the
ChatService to populate it. Go ahead and create the it with the following content:
We have declared three instance variables to be accessible from the
ChatComponent Template: me, other and messages. These are initialized with the data coming from the
Create the Interface
Let’s now display the data within our
ChatComponent Template. For our first iteration, we’ll focus on the display of the data as-is, without any styling or images. The interface will be split into three parts:
- the header, where the information about the other participant are displayed (photo, cover and name)
- the chat box, where the messages bubbles are displayed
- the message box, where the current can write and send a new message
chat.component.html Template and put the following content:
Before running the application to visualize the result, we need to reference the
ChatComponent selector within the
AppComponent. To do this, we first need to update the corresponding Module, located in
Now we can include include our selector within the
Notice that we didn’t have to reference any directive within the
AppComponent, since we’re doing it at the Module level.
Now, run your application and you should see this:
This is clearly not a useful interface. Let’s now work on the styling to improve this a little bit.
Style the Interface
Let’s start with the header. We will display the other user’s cover in the background, and the profile picture and the name on top of it.
chat.component.html and update it with the following content:
Then, we’ll style it using the folowing CSS:
The profile picture is rounded using a border-radius. We wrap it into a container which is also rounded and white-bordered in order to highlight it within the cover.
Let’s now work on the body of the interface, or the “chat box”. We want to instantly notice from whose sender is the message, so we’ll have to declare two sets of styles: one for ‘other’, one for ‘me’. We also want to display the sender’s profile picture beside every bubble.
We’ll start with the bubble styling. Open up the
chat.component.css Stylesheet and add the following properties:
This way, we have two main bubble classes with different colors and shift positions. How are we going to differentiate them among the messages in the ListView though? We’ll first declare a new method in
ChatComponent to get the bubble CSS class according to the given message:
Then, we’ll update the chat box ListView to include the styling:
This should now look like this:
This already starts to look like a chat interface, but we’re not over yet. We’ll now add the profile picture thumbnails beside each bubble. we’ll also alternate the photo position between right and left depending on the sender.
First, edit the chat box with the following content:
We’ve change the wrapping ‘bubble-container’ to a GridLayout instead of a StackLayout, in order to provide a floating layout to host the bubble aside with the sender’s picture. Then, we include the Image containing the picture below the bubble StackLayout.
It’s important to note that the images will be loaded along with every item in the ListView. In a real world application, we would probably cache them in order to improve the performance but this goes beyond the scope of this tutorial.
This brings us to the following styles:
which gives us the following result:
Let’s enhance the styling a bit, for instance by dropping this ugly line under the TextView, and reducing the size of the message-date Label:
It would also be nice if we could have a more readable date output for the messages. One way to do this is to introduce a Pipe that will format the date. We’ll use the moment library, that you can install running:
Now we can create a new Pipe and make use of moment’s
.fromNow() function to return the time when the message has been sent, relatively from the current date:
We then need to declare the Pipe within the
AppModule before we can use it:
Which gives us:
Let’s now tackle the last part of the interface, which is the message box. First, some styling:
Now, we’re going to handle the logic allowing the user to send a new message.
Send a new message
The first thing we need to do is to bind the (tap) event to a
sendMessage() function, which we’ll implement in the
ChatComponent. When the Send button is tapped, we will want to create a new message with the content of the mesage box, as well as scrolling down to it. In a real world application, we would also have to send a request to a backend to notify the new message but that is out of the scope of this post.
Go ahead and update the code for the Send Label:
Then, we will need a reference to both the chat box ListView and the newMessage TextView in the
Then, we’ll implement the actual
So the main method is
sendMessage(), which collect the content of the
newMessage TextView. After adding the message to the
mesages array, we call
scrollChatToBottom() which goes down to the last index within the array, corresponding to the recently added message. Note that we made the scroll asynchronous to make sure that we catch the right moment, where the item has been correctly set up within the ListView. Finally, we clear the text from the TextView and we focus on the
chatBox in order to hide the keyboard.
There is one last thing we need to do: scroll down to the bottom of the chat when the Component is initialized. We can do this by binding the
(loaded) event from the
chatBox ListView to the
scrollChatToBottom() method (which now has to be set to public instead of private):
And we’re now done with our Chat interface. You can now back it with your actual data model.
I hope this tutorial has been useful to you. If it’s the case, please share it and don’t hesitate to leave a comment in case of any trouble !Angular2, NativeScript. Bookmark the permalink.