Real time Chat App with OnsenUI and Horizon!

Onsen UI & Monaca Team
The Web Tub
Published in
5 min readJul 20, 2016

A lot of modern apps like Twitter or Facebook work in real time: They update themselves when new information is available without the user pulling to refresh. With modern real time database like RethinkDB and the JavaScript Framework Horizon this task is as easy as writing any other JavaScript Application. In this tutorial we will build a simple chat app with MobX and the React Components for Onsen UI.

The entire source code of the app is available at GitHub. You can try out the app here.

We will first have a look at RethinkDB and then later build our app.

What is RethinkDB and Horizon.js?

RethinkDB is a real time database. The difference to a traditional database is the ability to listen to database changes. This makes real time updates very easy. Horizon is a JavaScript framework that makes it easier to interact with RethinkDB. You can install Horizon by doing:

$ npm install -g horizon

With the following command one can start a simple Horizon server in development mode on port 5000:

$ hz serve --dev --bind all -p 5000

The parameter --bind all makes it accessible throughout the entire network. In development mode there is no user authentication and no security rule. For this tutorial we are not going to deal with authentication, if you are interested to learn about it, please check the documentation.

To start Horizon in our application we will need to just use the connect() function

import Horizon from '@horizon/client';
const horizon = Horizon();
horizon.onReady(() => {
console.log('horizon is ready');
});console.log('connect horizon');
horizon.connect();

For the chat app we will create two tables, one for the rooms which contains just the room names with their IDs, and a message table that will contain the roomID, the message itself and the username.

To create a room and messages we can write some simple functions:

createRoom: (roomName) => {
horizon('chatRooms').store({ name: roomName })
}
createMessage: (authorName, roomID, message) => {
horizon('messages').store({
author: authorName,
date: new Date(),
message: message,
roomID: roomID
});
}

The function createRoom creates a simple room with the provided room name and createMessage creates a message for the room. The interesting part is how we can listen to changes of the database. We want to get all the messages from one room ordered by their date:

horizon('messages').findAll({roomID: roomID}).order('date').watch().subscribe((data) => {
// update messages here
});

The nice part about this is that the function in subscribe will be called every time the data is updated. In React we could just update the state and have updated data with almost no code.

Amazingly, this is almost all the backend code we will need for our App! Now let’s start building using MobX and the React Components for Onsen UI.

Building the components in Onsen UI

The React Components for Onsen UI make it very easy to build simple pages with Navigation without too much code. Our application will contain two screens: The first one will be a simple login screen, where the user can enter the name of the chatroom and the user name. We will render everything in a component called App that will contain the children:

Before we start looking at the views, let’s look at the application state first. The application state is managed via MobX. MobX is a JavaScript library that uses observables to do certain actions automatically once an observed variable changes. In the case of React, MobX calls setState() if a variable changes which the state depends on. If you want to learn more about MobX, I highly recommend a look at our recent tutorial that uses MobX to create a simple stopwatch.

The following code defines the application state: Mainly it will contain the current username, chatroom, the database connection to Horizon and some additional page-related information. In MobX we mark variables with the decorator @observable to indicate that MobX should observe it. If they change, the associated views will call a rerender automatically. Functions marked with @action are functions that change observable variables and @computed functions getters that depend on observables that will be only updated once an associated variable is changed.

The Login Screen

In the following explanation we will only look at the structure and the basic interaction of the components, the curious reader can look the details up at GitHub.

For the navigation we will use Onsen UI Navigator: We provide it an initial route which will contain a component we will render to. In our case this component will be LoginPage.

The structure of the Login component will look something like this:

The LoginPage consists of an image, two inputs and a button. The application state is passed down to the component and updating is very simple, as can be seen on the UserInput:

Once the value changes, we just update the variable and MobX will automatically rerender the UserInput component and only this component, since the username is only displayed there.

After the username and room name is entered, we will either create a room if it does not already exist or load the initial one:

Chat Room Page

The second page will contain the main chat messages. On the left side your messages will be presented, while on the right side other people’s messages will be shown. Again, let’s look at a small overview of the messages:

The ChatRoomPage component consists of a toolbar at the top, a bottom toolbar at the bottom and the messages in the middle. We will use RethinkDB and MobX to update the view: Whenever a new message is received that is written by oneself, the view will scroll down. When a message is written by somebody else, a small popup message will be shown that one can click to go to the bottom. The code of the main component looks like this:

Conclusion

Horizon combined with Onsen UI makes it really simple and fast to build a real time chat application. There are many resources and videos to learn more about RethinkDB. I highly recommend this video and their website. If you have any questions or feedback feel free to ask in our community. We would also appreciate a 🌟 on our GitHub repo!

--

--