Create and use private rooms in an Angular 7 chat app with Chatkit

Create and use private rooms in an Angular 7 chat app with Chatkit

In this tutorial, I’ll show you how to build a chat app with Angular 7 and Chatkit. You’ll learn how public and private rooms work in Chatkit, and how to leverage each one in your application


If you want to grab the complete code used in this article, head to this GitHub repository and follow the instructions in the README.md file.


Prerequisites

Previous experience with building Angular and Node.js applications is a must, but you do not need to have used Chatkit before. You will also need Node.js (version 6 or later) as well as npm installed on your machine. Installation instructions for both Node and npm can be found on this page.


Sign up for Chatkit

To take advantage of Chatkit features in your application, you need to sign up for a free account from Pusher. Once your account has been made, you will be redirected to the Chatkit page. Create a new Chatkit instance for your application, then locate the Credentials tab on your instance’s dashboard and take note of the Instance Locator and Secret Key as we’ll be using them on the server and in the application code.

Next, hit the Console tab and create a new user and a new public room. You can follow the instructions on this page to learn how to do so. Take note of the room ID as we’ll be using it later.


Set up the application server

Create a new directory for this project in your filesystem and cd into it through your terminal application. Then run npm init -y from within your project directory to initialize your Node project with a package.json file.

The run the following commands to install all the dependencies we’ll be needing to build the application server:

    npm install express body-parser cors dotenv @pusher/chatkit-server -S

Next, create a .env file in the root of your project directory and paste in the credentials you retrieved from your Chatkit instance dashboard:

    // .env

PORT=5200
CHATKIT_INSTANCE_LOCATOR=<your chatkit instance locator>
CHATKIT_SECRET_KEY=<your chatkit secret key>

Next, create another file called server.js and add the following code into it:

    // server.js

require('dotenv').config({ path: '.env' });

const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const Chatkit = require('@pusher/chatkit-server');

const app = express();

const chatkit = new Chatkit.default({
  instanceLocator: process.env.CHATKIT_INSTANCE_LOCATOR,
  key: process.env.CHATKIT_SECRET_KEY,
});

app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.post('/users', (req, res) => {
  const { userId } = req.body;

  chatkit
    .createUser({
      id: userId,
      name: userId,
    })
    .then(() => {
      res.sendStatus(201);
    })
    .catch(err => {
      if (err.error === 'services/chatkit/user_already_exists') {
        console.log(`User already exists: ${userId}`);
        res.sendStatus(200);
      } else {
        res.status(err.status).json(err);
      }
    });
});

app.post('/authenticate', (req, res) => {
  const authData = chatkit.authenticate({
    userId: req.query.user_id,
  });
  res.status(authData.status).send(authData.body);
});

app.set('port', process.env.PORT || 5200);
const server = app.listen(app.get('port'), () => {
  console.log(`Express running → PORT ${server.address().port}`);
});

The /users endpoint creates a new user in your Chatkit instance with the provided userId if that ID doesn’t already exist. As for /authenticate, it’s used to authenticate users who try to connect to your Chatkit instance, but we don’t try to authenticate anyone here for the sake of brevity. This means that anyone who tries to connect to the chatroom would be granted access without any authentication flow.

That’s all we need to do on the server side. You can start the server with node server.js. It will be available on http://localhost:5200 unless you change the PORT variable in the .env file.


Bootstrap the Angular app

We’ll make use of the Angular CLI to build our app so that we can quickly get up and running. The first thing to do is install it globally using the following command:

    npm install -g @angular/cli

Once the command above finishes running, you should have access to the ng command in the terminal. Make sure you are at the root of your project directory, then execute the command below. When prompted to add Angular routing, hit N, and choose CSS as the preferred stylesheet format.

    ng new client

Following that, cd into the client folder and install the additional dependencies that we’ll be making use of on the frontend of the application, which are the axios library for making HTTP requests, and the Chatkit client SDK for interacting with our Chatkit instance.

    npm install axios @pusher/chatkit-client -S

You can start the development server by running ng serve from within the client directory. The app should be available at http://localhost:4200.


Add the markup and styles for the application

Before we write the application logic, let’s add some markup and styles for the app. Open up client/src/app/app.component.html and change it to look like this:

    // client/src/app/app.component.html

<div class="App">
  <aside class="sidebar left-sidebar"></aside>
  <main class="chat-window"></main>
  <aside class="sidebar right-sidebar"></aside>
</div>

Basically, there are three main aspects to the UI: the left sidebar which holds the list of users in each room, the main chat window where messages are sent and viewed, and the right sidebar which lists all the rooms that the logged in user belongs to.

Let’s go ahead and add the styles for the app. Download the Skeleton CSS boilerplate, extract the zip file and copy normalize.css and skeleton.css from the css folder to your client/src/assets directory. Then open up client/src/style.css and change it to look like this:

    // client/src/style.css

@import 'assets/normalize.css';
@import 'assets/skeleton.css';

body {
    overflow: hidden;
    margin: 0;
}

Next, change the contents of client/src/app/app.component.css to look like this:

    // client/src/app/app.component.css

.App {
  width: 100%;
  height: 100vh;
  overflow: hidden;
  display: flex;
  border: 1px solid #ccc;
  color: #333;
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
  margin: 0;
}

h4 {
  margin-bottom: 10px;
}

ul {
  list-style: none;
}

form {
  margin-bottom: 0;
}

input[type="text"] {
  color: #333;
  border-radius: 0;
}

.sidebar {
  flex-basis: 15%;
  flex-shrink: 0;
  flex-grow: 0;
  background-color: #300d4f;
  color: #fff;
  padding: 10px 10px;
}

.left-sidebar section {
  margin-bottom: 20px;
}

.left-sidebar {
  display: flex;
  flex-direction: column;
}

.room-members {
  flex-grow: 1;
}

.right-sidebar .room {
  display: flex;
}

.newUser-input {
  margin-bottom: 0;
}

.right-sidebar {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding-left: 0;
  padding-right: 0;
}

.room {
  padding: 5px 10px;
  cursor: pointer;
}

.room:hover {
  background-color: goldenrod;
  color: #333;
}

.room.active {
  background-color: #11D771;
  color: #333;
}

.room-name {
  display: inline-block;
  margin-left: 10px;
}

.user-list li {
  margin-bottom: 10px;
  font-size: 16px;
  display: flex;
  align-items: center;
}

.presence {
  display: inline-block;
  width: 20px;
  height: 20px;
  background-color: #fff;
  margin-right: 10px;
  border-radius: 50%;
}

.presence.online {
  background-color: green;
}

.chat-window {
  display: flex;
  flex-grow: 1;
  flex-direction: column;
  justify-content: space-between;
}

.chat-header, .chat-footer {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.chat-header {
  border-bottom: 1px solid #ccc;
  padding: 10px 20px;
  height: 40px;
}

.chat-header h4 {
  margin-bottom: 0;
}

.chat-session {
  flex-grow: 1;
  padding: 10px 20px;
  overflow-y: auto;
}

.message-list {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.user-message {
  margin-top: 10px;
}

.user-message span {
  display: block;
}

.user-id {
  font-weight: bold;
}

.chat-footer {
  padding: 0;
  border-top: 1px solid #ccc;
  height: 50px;
}

.message-form {
  width: 100%;
  height: 100%;
}

.message-input {
  width: 100%;
  border: none;
  margin-bottom: 0;
  height: 100%;
}

.message-input:focus {
  border: none;
}

.send-message {
  background-color: #300d4f;
  color: #fff;
  border: 1px solid #300d4f;
  padding: 10px;
}

.create-room {
  padding: 0 10px;
}

.create-room button {
  display: block;
}

input[type="checkbox"] {
  margin-bottom: 0;
  display: inline-block;
  margin-right: 5px;
}

.is-private {
  display: flex;
  align-items: center;
}

.user-rooms h4, .joinable-rooms h4 {
  padding-left: 10px;
}

At this point, the app should look like this:


Identify the user

Add the following code to your app.component.html file:

    // client/src/app/app.component.html

<div class="App">
  <aside class="sidebar left-sidebar">
    <section *ngIf="!currentUser.id" class="join-chat">
      <h4>Join Chat</h4>
      <form (ngSubmit)="addUser()">
        <input placeholder="Enter your username" type="text" name="userid" [(ngModel)]="userId" />
      </form>
    </section>
  </aside>
  <main class="chat-window"></main>
  <aside class="sidebar right-sidebar"></aside>
</div>

Since we’re dealing with forms, we need to import FormsModule which exports the required providers and directives for template-driven forms and makes them available in our AppComponent:

    // client/src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})

export class AppModule { }

Now, change app.component.ts to look like this:

    // client/src/app/app.component.ts

import { Component } from '@angular/core';
import Chatkit from '@pusher/chatkit-client';
import axios from 'axios';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  userId = '';
  currentUser = <any>{};

  addUser() {
    const { userId } = this;
    axios.post('http://localhost:5200/users', { userId })
      .then(() => {
        const tokenProvider = new Chatkit.TokenProvider({
          url: 'http://localhost:5200/authenticate'
        });

        const chatManager = new Chatkit.ChatManager({
          instanceLocator: '<your chatkit instance locator>',
          userId,
          tokenProvider
        });

        return chatManager
          .connect()
          .then(currentUser => {
            this.currentUser = currentUser;
          });
      })
        .catch(error => console.error(error))
  }
}

Replace <your chatkit instance locator> as appropriate.

When someone wants to use the app, we need them to provide their username before they can be connected.

We can do this with a simple form that will take a user ID, and on form submission, send it to the /users endpoint we created earlier so that a new Chatkit user can be created if one with that user id doesn’t exist.


Add user to room

Now that the user is connected to our Chatkit instance, we need to connect the user to a room and subscribe to new messages. We also need to display the users who are present in the room and their current status (online or offline).

Let’s modify the app.component.html file to look like this:

    // client/src/app/app.component.html

&lt;div class="App"&gt;
  &lt;aside class="sidebar left-sidebar"&gt;
    &lt;section *ngIf="!currentUser.id" class="join-chat"&gt;
      &lt;h4&gt;Join Chat&lt;/h4&gt;
      &lt;form (ngSubmit)="addUser()"&gt;
        &lt;input placeholder="Enter your username" type="text" name="userid" [(ngModel)]="userId" /&gt;
      &lt;/form&gt;
    &lt;/section&gt;
    &lt;section *ngIf="currentUser.id" class="room-members"&gt;
      &lt;h4&gt;Room Users&lt;/h4&gt;
      &lt;ul class="user-list"&gt;
        &lt;li *ngFor="let user of roomUsers"&gt;
          &lt;span class="presence {{ user.presence.state }}"&gt;&lt;/span&gt;
          &lt;span&gt;{{ user.name }}&lt;/span&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/section&gt;
  &lt;/aside&gt;

  &lt;main class="chat-window"&gt;
    &lt;header class="chat-header"&gt;
      &lt;h4 *ngIf="!currentRoom.name; else roomName"&gt;Chat&lt;/h4&gt;
      &lt;ng-template #roomName&gt;
        &lt;h4&gt;{{ currentRoom.name }}&lt;/h4&gt;
      &lt;/ng-template&gt;
      &lt;span class="participants"&gt;&lt;/span&gt;
    &lt;/header&gt;
    &lt;section class="chat-session"&gt;
      &lt;ul class="message-list"&gt;
        &lt;li class="user-message" *ngFor="let message of messages"&gt;
          &lt;span class="user-id"&gt;{{ message.senderId }}&lt;/span&gt;
          &lt;span&gt;{{ message.text }}&lt;/span&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/section&gt;
  &lt;/main&gt;
  &lt;aside class="sidebar right-sidebar"&gt;&lt;/aside&gt;
&lt;/div&gt;

We’ve added three new blocks here. The .room-members section displays all the current members of the room and shows whether they are online or not, while the .chat-header displays the current room name or a generic “Chat” message if the user is not connected to a room. Finally, .chat-session is where messages for the room are displayed.

Change app.component.ts to look like this:

    // client/src/app/app.component.ts

import { Component } from '@angular/core';
import Chatkit from '@pusher/chatkit-client';
import axios from 'axios';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  userId = '';
  currentUser = &lt;any&gt;{};
  messages = [];
  currentRoom = &lt;any&gt;{};
  roomUsers = [];
  userRooms = [];

  connectToRoom(id) {
    this.messages = [];
    const { currentUser } = this;

    currentUser.subscribeToRoom({
      roomId: `${id}`,
      messageLimit: 100,
      hooks: {
        onMessage: message =&gt; {
          this.messages.push(message);
        },
        onPresenceChanged: () =&gt; {
          this.roomUsers = this.currentRoom.users.sort((a) =&gt; {
            if (a.presence.state === 'online') return -1;

            return 1;
          });
        },
      },
    })
    .then(currentRoom =&gt; {
      this.currentRoom = currentRoom;
      this.roomUsers = currentRoom.users;
      this.userRooms = currentUser.rooms;
    });
  }

  addUser() {
    const { userId } = this;
    axios.post('http://localhost:5200/users', { userId })
      .then(() =&gt; {
        const tokenProvider = new Chatkit.TokenProvider({
          url: 'http://localhost:5200/authenticate'
        });

        const chatManager = new Chatkit.ChatManager({
          instanceLocator: '&lt;your chatkit instance locator&gt;',
          userId,
          tokenProvider
        });

        return chatManager
          .connect()
          .then(currentUser =&gt; {
            this.currentUser = currentUser;
            this.connectToRoom('&lt;your chatkit room id&gt;');
          });
      })
        .catch(error =&gt; console.error(error))
  }
}

Replace <your chatkit room id> with the ID of the room you created earlier. As you can see, once a user has been added to our Chatkit instance, we try to add them to a room using the connectToRoom() method.

In connectToRoom(), the subscribeToRoom method is used to add the current user to a chatroom with the ID you provided, and any existing messages in the room will be displayed depending on the number you set in messageLimit. Here, the most recent 100 messages in the room will be shown.

The onMessage hook is triggered when a new message is sent to the chatroom. We append the new message to the messages array so that the new message is displayed in the chat window. Likewise, the onPresenceChanged hook tells us when a member of the room comes online or goes offline so that we can update the status of the user on the sidebar.

Now, when you connect to Chatkit, the room name will be displayed in .chat-header while the room members will be displayed on the sidebar. You can add other users aside from the one you already created by refreshing the page and entering a new username in the Join Chat form.

Because no new messages have been sent yet, nothing is displayed in .chat-session. Let’s change this by adding the ability to send messages to the app.


Sending messages

Let’s allow users to send messages by first creating a message form in app.component.html:

    // client/src/app/app.component.html

...
  &lt;main class="chat-window"&gt;
    &lt;header class="chat-header"&gt;
      &lt;h4 *ngIf="!currentRoom.name; else roomName"&gt;Chat&lt;/h4&gt;
      &lt;ng-template #roomName&gt;
        &lt;h4&gt;{{ currentRoom.name }}&lt;/h4&gt;
      &lt;/ng-template&gt;
      &lt;span class="participants"&gt;&lt;/span&gt;
    &lt;/header&gt;
    &lt;section class="chat-session"&gt;
      &lt;ul class="message-list"&gt;
        &lt;li class="user-message" *ngFor="let message of messages"&gt;
          &lt;span class="user-id"&gt;{{ message.senderId }}&lt;/span&gt;
          &lt;span&gt;{{ message.text }}&lt;/span&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/section&gt;
    &lt;footer *ngIf="currentUser.id" class="chat-footer"&gt;
      &lt;form class="message-form" (ngSubmit)='sendMessage()'&gt;
        &lt;input class="message-input" placeholder="Type a message. Hit Enter to send" type="text" name="message" [(ngModel)]="newMessage" /&gt;
      &lt;/form&gt;
    &lt;/footer&gt;
  &lt;/main&gt;
...

Then update app.component.ts like this:

    // client/src/app/app.component.ts

...
  roomUsers = [];
  userRooms = [];
  newMessage = '';

  connectToRoom(id) {
    this.messages = [];
    const { currentUser } = this;

    currentUser.subscribeToRoom({
      roomId: `${id}`,
      messageLimit: 100,
      hooks: {
        onMessage: message =&gt; {
          this.messages.push(message);
        },
        onPresenceChanged: () =&gt; {
          this.roomUsers = this.currentRoom.users.sort((a) =&gt; {
            if (a.presence.state === 'online') return -1;

            return 1;
          });
        },
      },
    })
    .then(currentRoom =&gt; {
      this.currentRoom = currentRoom;
      this.roomUsers = currentRoom.users;
      this.userRooms = currentUser.rooms;
    });
  }

  sendMessage() {
    const { newMessage, currentUser, currentRoom } = this;

    if (newMessage.trim() === '') return;

    currentUser.sendMessage({
      text: newMessage,
      roomId: `${currentRoom.id}`,
    });

    this.newMessage = '';
  }

...

When the .message-form is submitted, we access the currentUser and call sendMessage() on it. This sends the message to the chat room and, thanks to the onMessage hook, new messages are displayed on the screen instantly.


Create new rooms

Right now, we are limited to just the one room that was created in our Chatkit instance dashboard. Let’s make it possible for users to create new rooms right from the chat app. You can create both public and private rooms as you’ll see below.

Modify app.component.html like this:

    // client/src/app/app.component.html

...

  &lt;aside class="sidebar right-sidebar"&gt;
    &lt;section class="room-section"&gt;
      &lt;section *ngIf="currentUser.id" class="user-rooms"&gt;
          &lt;h4&gt;Rooms&lt;/h4&gt;
          &lt;ul class="room-list"&gt;
            &lt;li *ngFor="let room of userRooms"&gt;
              &lt;div [class.active]="room.id==currentRoom.id" (click)="connectToRoom(room.id)" class="room"&gt;
                &lt;span class="room-status" *ngIf="room.isPrivate; else publicRoom"&gt;🔒&lt;/span&gt;
                &lt;ng-template #publicRoom&gt;
                  &lt;span&gt;🌐&lt;/span&gt;
                &lt;/ng-template&gt;
                &lt;span class="room-name"&gt;{{ room.name }}&lt;/span&gt;
              &lt;/div&gt;
            &lt;/li&gt;
          &lt;/ul&gt;
        &lt;/section&gt;
        &lt;section *ngIf="joinableRooms.length &gt; 0" class="joinable-rooms"&gt;
            &lt;h4&gt;Joinable rooms&lt;/h4&gt;
            &lt;ul class="room-list"&gt;
                &lt;li *ngFor="let room of joinableRooms"&gt;
                  &lt;div class="room" (click)="joinRoom(room.id)"&gt;
                    &lt;span class="room-status" *ngIf="room.isPrivate; else publicRoom"&gt;🔒&lt;/span&gt;
                    &lt;ng-template #publicRoom&gt;
                      &lt;span&gt;🌐&lt;/span&gt;
                    &lt;/ng-template&gt;
                    &lt;span class="room-name"&gt;{{ room.name }}&lt;/span&gt;
                  &lt;/div&gt;
                &lt;/li&gt;
              &lt;/ul&gt;
        &lt;/section&gt;
    &lt;/section&gt;
    &lt;section *ngIf="currentUser.id" class="create-room"&gt;
      &lt;form (ngSubmit)="createRoom()"&gt;
        &lt;input type="text" [(ngModel)]="newRoom.name" name="room-name" id="room-name" placeholder="Create a room"&gt;
        &lt;label for="is-private"&gt;
            &lt;input type="checkbox" [(ngModel)]="newRoom.isPrivate" name="is-private" id="is-private"&gt;
            &lt;span&gt;Is this room private?&lt;/span&gt;
        &lt;/label&gt;
      &lt;/form&gt;
    &lt;/section&gt;
  &lt;/aside&gt;

..

The .user-rooms section displays a list of rooms that the user belongs to. Public rooms are denoted with a globe emoji (🌐) in front of the room name while private rooms have a lock emoji instead. Under it, we have the .joinable-rooms section that shows the public rooms that the current user is able to join (but isn’t yet a member of). Finally, we have a form at the bottom of the right sidebar that allows the current user to create a new room.

Next, update app.component.ts to look like this:

    // client/src/app/app.component.ts

...

  userRooms = [];
  newMessage = '';
  newRoom = {
    name: '',
    isPrivate: false
  };
  joinableRooms = [];

  createRoom() {
    const { newRoom: { name, isPrivate }, currentUser } = this;

    if (name.trim() === '') return;

    currentUser.createRoom({
      name,
      private: isPrivate,
    }).then(room =&gt; {
      this.connectToRoom(room.id);
      this.newRoom = {
        name: '',
        isPrivate: false,
      };
    })
    .catch(err =&gt; {
      console.log(`Error creating room ${err}`)
    })
  }

  getJoinableRooms() {
    const { currentUser } = this;
    currentUser.getJoinableRooms()
    .then(rooms =&gt; {
      this.joinableRooms = rooms;
    })
    .catch(err =&gt; {
      console.log(`Error getting joinable rooms: ${err}`)
    })
  }

  joinRoom(id) {
    const { currentUser } = this;
    currentUser.joinRoom({ roomId: id })
    .catch(err =&gt; {
      console.log(`Error joining room ${id}: ${err}`)
    })
  }

...

  addUser() {
    const { userId } = this;
    axios.post('http://localhost:5200/users', { userId })
      .then(() =&gt; {
        const tokenProvider = new Chatkit.TokenProvider({
          url: 'http://localhost:5200/authenticate'
        });
        const chatManager = new Chatkit.ChatManager({
          instanceLocator: '&lt;your chatkit instance locator&gt;',
          userId,
          tokenProvider
        });
        return chatManager
          .connect({
            onAddedToRoom: room =&gt; {
              this.userRooms.push(room);
              this.getJoinableRooms();
            },
          })
          .then(currentUser =&gt; {
            this.currentUser = currentUser;
            this.connectToRoom('&lt;your chatkit room id&gt;');
            this.getJoinableRooms();
          });
      })
        .catch(error =&gt; console.error(error))
  }

...

The getJoinableRooms() method displays the joinable rooms for the current user on the right (if any), while the joinRoom() method allows the current user to join any room that is listed under Joinable Rooms with one click. createRoom() on the other hand, is invoked when the form at the bottom of the right sidebar is submitted. It creates a new room in our Chatkit instance and adds the current user to the room automatically.

Try it out. Connect a user to the app. Only one room will be listed under Rooms, but you can create more using the form on the bottom right. Create a few public and private rooms as shown in the screenshot below. You will be able to switch between the rooms by clicking on the room name.

The current user (Peter in my case) does not have any joinable rooms, because he already belongs to all of them. Open the chat app in a new tab and login as another user. You will see that the user can join any of the public rooms that Peter created simply by clicking on any of them.


Add users to a private room

Private rooms are not listed under Joinable Rooms which means only the current members of the rooms can see them. Let’s finish up by making it possible for members of private rooms to add other users to the rooms.

Open up app.component.html and change it to look like this:

    // client/src/app/app.component.html

...
  &lt;aside class="sidebar left-sidebar"&gt;
    &lt;section *ngIf="!currentUser.id" class="join-chat"&gt;
      &lt;h4&gt;Join Chat&lt;/h4&gt;
      &lt;form (ngSubmit)="addUser()"&gt;
        &lt;input placeholder="Enter your username" type="text" name="userid" [(ngModel)]="userId" /&gt;
      &lt;/form&gt;
    &lt;/section&gt;
    &lt;section *ngIf="currentUser.id" class="room-members"&gt;
      &lt;h4&gt;Room Users&lt;/h4&gt;
      &lt;ul class="user-list"&gt;
        &lt;li *ngFor="let user of roomUsers"&gt;
          &lt;span class="presence {{ user.presence.state }}"&gt;&lt;/span&gt;
          &lt;span&gt;{{ user.name }}&lt;/span&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/section&gt;
    &lt;form *ngIf="currentRoom.isPrivate" (ngSubmit)="addUserToRoom()"&gt;
      &lt;label for="user-name"&gt;Add user to {{ currentRoom.name }}&lt;/label&gt;
      &lt;input type="text" class="newUser-input" [(ngModel)]="newUser" name="user-name" id="user-name" placeholder="Enter username"&gt;
    &lt;/form&gt;
  &lt;/aside&gt;
...

Then update app.component.ts like this:

    // client/src/app/app.component.ts
...
newRoom = {
name: '',
isPrivate: false
};
joinableRooms = [];
newUser = '';

  addUserToRoom() {
    const { newUser, currentUser, currentRoom } = this;
    currentUser.addUserToRoom({
      userId: newUser,
      roomId: currentRoom.id
    })
      .then((currentRoom) =&gt; {
        this.roomUsers = currentRoom.users;
      })
      .catch(err =&gt; {
        console.log(`Error adding user: ${err}`);
      });

    this.newUser = '';
  }

...

A new form has been added to the bottom left. Once you enter a username and submit the form, the user will be added to the room and the room would be displayed under the users’ Rooms instantly, so that they can connect to the room and participate in conversation.


Wrap up

This concludes my tutorial. In this article, you built a complete chat application with public and private rooms without doing anything particularly complex since Chatkit does all the heavy lifting for us.

You can checkout other things Chatkit can do by viewing its extensive documentation. Don’t forget to grab the complete source code in this GitHub repository.


Originally published by Ayooluwa Isaiah at https://pusher.com

Important reasons for developers to adopt Angular JS development

 Important reasons for developers to adopt Angular JS development

In the current scenarios, e-commerce companies are very keen to create an online impact. The web and app development market are at its peak of popularity. There is a high demand for web and app developers with a growing number of websites. Angular...

In the current scenarios, e-commerce companies are very keen to create an online impact. The web and app development market are at its peak of popularity. There is a high demand for web and app developers with a growing number of websites. Angular has been a top choice for web development and it's the latest version AngularJS has gained popularity in the industry. This java script framework has created its prominent position in creating web apps.
Regardless of whether there are numerous different systems accessible for web development, AngularJS can support among them all. Since its introduction in the market, Angular has been creating waves in the market.

Introduction

Angular js is a powerful framework that was developed by Google. It is used to build dynamic apps with power-packed features. It was first introduced in 2010 and created by developers at Google. This framework was created to simplify and remove the challenges in creating dynamic apps. It uses HTML, CSS, and java script to create dynamic single-page applications. Angular Js is inclusive of Mongo DB and it is a frontend fragment of Mean Stack. In the developer's community, Angular is considered as a reliable and fast Java script framework. Many popular apps like PayPal. You tube, Netflix, the guardian, Lego are built using the AngularJS framework.

In this blog, we are listing some compelling reasons to pick angular development to familiarize you with its potential

• Open-source framework: It is not a library but open-source frameworks that enable the developers to build well-performing single page web applications. Just after its launch, it became hugely popular among the developers and it is not going to come at a halt.

• Simplified MVC structure: Developers use AngularJS to build robust and interactive web applications. AngularJS framework uses MVC architecture to create interactive applications. AngularJS makes it easy for developers to create apps as they are only required to split the applications.

• Extensive community: As angular is built by Google, it is backed by a very large community of professionals. The Angular JS conferences of the professionals are held all over the world. Hackathons are also organized in IT communities that include some professional and skilled engineers who can help with the queries and questions related to Angular.

• Declarative code system: In Angular JS developers can create declarative patterns by using declarative paradigms. It enables developers to be less heavy, and easy to read. In this framework, the developers get data models that are not too complex to write that abolishes the need to use any getter/setters and with easy data manipulation.

• Two-way data binding: It is one of the impeccable features that makes Angularjs popular in the developers' community. It allows seamless projections of the models and data binding. In this framework, any changes in the user interface make an impact on the application objects. The developers are not required to fresh the cycle and that makes it vulnerable to bugs.

• Using directives: AngularJS makes use of Directives as the developers can build custom HTML tags that function as custom widgets and it can be possible using directives. Its implications are also in the case of the use of decorating components and manipulation of DOM elements in appealing ways.

• Enterprise-level testing: When using Angular JS there is no need for demanding any other supplementary framework or additional plugins. In the process, parts of applications are put in the angular framework which is not too complex for manipulation. In module separation, developers can load essential services in an effective way for the performance of automatic testing.

• Client-side situation: AngularJS mainly works at the client-side and it is fully compatible with both web and mobile browsers. It can function with any projects without the need for any backend notifications. The developers can easily use AngularJS for the front end of applications.

• Easy to use: AngularJS is rich with its features and facilitates developers to reduce any need for writing codes. It reduces the burden of developers by the application of MVC architecture and data models.

Many other significant features make AngularJS prioritize by the developers than other Javascript frameworks. The above-mentioned reasons have made it the top choice for reputed companies all across the globe for web development. Developers at the company master the skills to work with Angular JS development for web. The company is equipped with dedicated professionals having sound technical knowledge of working with AngularJS. We offer offshore services to extend our reach all across the globe with various models. We have more than 15 years of experience in the industry that we use to deliver high-quality solutions by leveraging the latest technology and quality standards.

Mobile App Development Company India | Ecommerce Web Development Company India

Mobile App Development Company India | Ecommerce Web Development Company India

Best Mobile App Development Company India, WebClues Global is one of the leading web and mobile app development company. Our team offers complete IT solutions including Cross-Platform App Development, CMS & E-Commerce, and UI/UX Design.

We are custom eCommerce Development Company working with all types of industry verticals and providing them end-to-end solutions for their eCommerce store development.

Know more about Top E-Commerce Web Development Company

Hire PHP Developer and Web Developer for your Online Business

Hire PHP Developer and Web Developer for your Online Business

PHP is widely used open-source scripting language it helps in making dynamically easy your websites and web application. Mobiweb Technology is your best technical partner and offering you solution for any kind of website and application...

PHP is widely used open-source scripting language it helps in making dynamically easy your websites and web application. Mobiweb Technology is your best technical partner and offering you solution for any kind of website and application development. To hire PHP developer and web developer at affordable prices contact Mobiweb Technology via [email protected]