How to create a chat group for anonymous users online

How to create a chat group for anonymous users online

Learn how to build an anonymous group chat with Angular 7

To follow this post, some basic knowledge of Angular is required. Since we’re using Angular we’re gonna also see some TypeScript code. Some basic knowledge here would also help. One would need Node 10 or any newer version installed, in order to play with the sample code from GitHub. That’s all, having this, following this tutorial should be straight forward.

We’ll not focus on the UI that much, more on the functional part, but here’s how it will look in the end:


Login screen for our demo app


Group screen for our demo app

The code is on GitHub here, in case you want to dive right in. Clone the repo and have fun, don’t forget to get back to the article to follow the tutorial 😉

New project

The first thing we have to do is create a new project so we can work on our awesome application. For this we need the Angular CLI, installed globally:

npm install -g @angular/cli

And then we can create the project:

ng new AngularChat

Or we can use npx, the node package runner. We achieve the same result, without having to install anything globally:

npx @angular/cli new AngularChat

Follow the interactive installation. Say yes to routing and pick CSS when asked what stylesheet format you want to use.

This will generate all the structure and code required for a new Angular application. It will also install all the dependencies. Once the command has finished running, you can open the new folder in your preferred editor(I love VsCode). You can start the local development server by running npm start or ng serve. The two commands do the same thing. Now you can go to http://localhost:4200 and see the application up and running.

CometChat Pro account

The second important thing that we need to do, is to create a free CometChat Pro account.

You can go to the website and click on the big red button that says “Get started for free”. Once you fill in all the required information you’ll have a trial account setup and ready to go.

On the CometChat dashboard, you’ll see an overview of your account. In the ‘Add new app’ dialog, enter a name and click the plus sign to create a new application. Take note of the Application ID as we’ll use it to communicate with the ComeChat API.

From the left side menu, go to API Keys, since we’ll have to create a new one for our application. Give it whatever name suits you, and select Auth Only as scope. Take a note of this API Key since we’ll use it in the application.

The CometChat app comes with five users and a group already created, so we have everything we need. The existing users are: superhero1, superhero2, superhero3, superhero4 and naturally, superhero5. One group that would fit all these five is supergroup. You can see them all using the CometChat dashboard.

CometChat SDK

With all this in place, we now add the CometChat package to our application. This will help us work more easily with the API. Instead of us having to make all the calls we can use pre-made functions for the operations that we want to make.

To add the package run:

npm install @cometchat-pro/chat

Now we can reference the library in our project, and use whatever functions we need from there in our code:

import { CometChat } from '@cometchat-pro/chat';
TypeScript type definitions

At the time of this writing, the library does not have TypeScript type definitions. Though this is something that might come 😉 .

All Angular/TypeScript developers love type definitions. To make it easier to follow the tutorial and play with the code, I’ve created a few, for the functions that we’re going to use.

This was done by creating a new *.d.ts file inside the src folder of our app. The TypeScript compiler will pick it up and show us the type definitions when working with the code. This is not something you need to do, but if curious you can have a look at the file on GitHub.

Application structure

Now let’s think about our application a bit, we want an anonymous chat, so this will be a component. But before we get to this component we also want to allow the user to login to our application. So we’ll need another component for that. Also it’s a best practice to wrap the usage of a library inside a service, so we’ll need a CometChat service class also.

With this in mind, we’ll use the Angular CLI to generate these components for us. If you installed the CLI globally at the beginning you can use the ng command. If not, you can use the locally installed one by running npm run ng.

Now to generate our components:

ng generate component components/Login
ng generate component components/GroupView

We pass the generate argument first, to tell the CLI what we want to do. Then we specify the blueprint of what we want to generate, in this case a component. Then we specify the name of the component. In our case I’ve also added components/ before the actual name so that all the components are in the same folder.

To create the service class:

ng generate service services/CometChat

Same thing as before. We changed the blueprint to service this time and specified a services folder for this class to be in.

Now we have the structure of our application in place.

Routing

We have our two components in place, now we have to tell Angular when to load them.

In our App routing module (app-routing.module.ts) we can update the routes like this:

const routes: Routes = [
  { path: '', redirectTo: 'login', pathMatch: 'full' },
  { path: 'login', component: LoginComponent },
  { path: 'chat', component: GroupViewComponent },
];


The first one is a redirect when our application starts we want to go to the login path. The second one tells Angular that whenever we go to login we want to show the LoginComponent. The second one does the same but with the chat path and the GroupViewComponent.

We can now go on and implement some functionality in our application.

Initialising CometChat

The first thing we need to do to use the CometChat SDK is to initialise it. This has to be done before calling any other methods. Due to this, a good place to implement it would be when our application initializes. Meaning the ngOnInit hook of the app component.

In our CometChat service, we create an init method. It will have only one parameter, the application ID. Inside, we’ll call the init method of the CometChat library:

init(apiKey: string) {
  CometChat.init(apiKey).then(
    msg => console.log('Initialized succesfull: ', msg),
    err => console.log('Initialization failed: ', err),
  );
}


The init method will return a Promise. While it’s not mandatory, it’s a good practice to handle the result using a then call. Printing some messages in case of success or failure is enough for us to make it easier to debug the code.

In our app component we have to add the service as a parameter to the constructor:

constructor(private cometChat: CometChatService) {}

You can notice that before the name there is the private access modifier. This is a nice little trick in TypeScript that allows us to create a field with this name on the class.

We can move on and initialise CometChat when our application starts, so in the same app component:

ngOnInit() {
  this.cometChat.init('CometChatApp ID');
}

Global config values

It’s a good practice to keep global values in the same file. A good place to do this is the angular environment config files(environment.ts). We already have an object called environment there. We can add a property on it with the values for the CometChat application id and API key:

export const environment = {
  production: false,
  cometChat: {
    apiKey: 'API_KEY_HERE',
    appId: 'APP_ID_HERE',
  }
}

This will allow us to reference them through the application whenever needed. So in the example above, instead of hardcoding the value we can do:

this.cometChat.init(environment.cometChat.appId);
Login component

Everything is initialized. Now we can move on and allow the user to authenticate to our application.

For this we are gonna use the login function from CometChat. This allows a user to be authenticated based on a user id and API key. Even though this is an anonymous chat app, we need to authenticate to the CometChat API so that we can read and write information related to our application.

Inside our CometChat service, we create a new login method and perform the call:

login(userId: string) {
  return CometChat.login(userId, environment.cometChat.apiKey)
  .then(
    user => console.log('Login succesfull: ', user),
    err => console.log('Login failed: ', err),
  );
}

We pass in the user id and use the API key from the environment object. And as we did before, we handle the outcome Promise result by writing some values in the console. This method also returns the result of the API call. We handle it here, but we also want to know where we use it if it’s successful or not.

When successful, the result of this method call will be the logged in user. It might be useful to hold onto it. So let’s create a local user property and assign it when we have a response.

user => {
  console.log('Login succesfull: ', user);
  this.currentUser = user;
}

With this in place we can move on and add an input where the user can enter a name and a submit button. In our login component html template we’ll have this code:

Username

Join chat

When the user clicks the ‘Join chat’ button, we will take the text value from the input and call the login method in our class. As we did in the application component. We have to use dependency injection to get an instance of the CometChat service:

constructor(private cometChat: CometChatService, private router: Router) {}

We also have the Angular Router there since we’ll use it to navigate to the group chat page.

Inside the login method, we’ll call the CometChat service. If the login is successful, we redirect the user to the chat page:

login(userId: string) {
  this.cometChat
    .login(userId)
    .then(() => this.router.navigateByUrl('chat'))
}

If everything goes ok, once a user enters a valid name and hits join they can get to our group view component.

Group view component

This is our most complex component and where most of the action will take place. We’ll be able to see messages here and write new ones.

To make things easier we’ll start with the template. We need a list, to show all the messages and an input with a button, to allow users to write new messages. For the list of messages we can have something like this:


  
    *{{ message.sender.uid }}* 

    {{ message.text }}
  



We iterate over messages collection using the ngForOf directive from Angular. For each message, we show the sender uid. This means the name of the user that wrote the message, and the text of the message.

We also use the ngClass directive to add a css class only to messages that were written by the logged in user. This is something we’re used to from most chat apps. Usually, they have a different color or placed in a different position on the screen.

For this to work we need to have the properties defined in our class:

messages = [];
    
get currentUser() {
  return this.chatService.currentUser;
}

Here we can see where we’re actually using the currentUser that we’ve stored when the login is performed.

As before, the CometChat service is added in the constructor as a parameter:

constructor(private chatService: CometChatService) {}

Good, now we also have to show some messages 🙂. There are two parts to this, we need to fetch existing messages, that were written before. And after that, we need to register a listener for any new message that might arrive.

Previous messages

To fetch messages, we need to build something like a query and specify what we want to retrieve. The SDK has the MessagesRequestBuilder class that allows us to do exactly this.

We have different methods on it, in a fluent-like API, that allows us to set different properties for our request:

  • number of messages to retrieve
  • user or group id
  • filtering methods like timestamp or message id

In our case we want to fetch messages from a group, so we need to specify only the group id. Ok, maybe a limit would also be a sensible thing to add 😃. After we’ve set all the properties we want we can call the build method. This will create the query and give us back an instance of MessageRequest that we can use to fetch messages:

getPreviousMessages(groupId: string) {
  const messageRequest = new CometChat.MessagesRequestBuilder()
    .setGUID(groupId)
    .setLimit(100)
    .build();
    return messageRequest.fetchPrevious();
}


The message request class has two methods: fetchNext and fetchPrevious. As the name suggests, next will get messages after the filters, similar to greater than. Previous will get the messages before, or lower than.

In our case, we did not set any filter so any of the two should work. The method above was added to the CometChat service class. We can call it in our group view component to fetch the previous messages:

this.chatService
  .getPreviousMessages('supergroup')
  .then(messages => (this.messages = messages))


When we get the response back, we assign the messages to the local property. Angular will notice there is something new and will render our component with the new values.

Message listener

We already have messages that were previously written, but we also want to show incoming, real-time, messages. Messages that other users might write as we look at the screen. To get them we need to register a message listener. For this we need a unique listener ID. Something related to the screen or part of the application the chat is linked to. We can then use the MessageListener class to register handlers for different type of messages:

listenForMessages(listenerId: string, onMessageReceived: (msg: any) => void) {
  CometChat.addMessageListener(
    listenerId,
    new CometChat.MessageListener({
      onTextMessageReceived: onMessageReceived,
    })
  );
}


For now, we only care about text messages. That’s the only listener we’ve registered. But it also has properties like onMediaMessageReceived and onCustomMessageReceived for other types.

Having added the above method to the CometChat service class, we can use it in our group view component. After we’ve read all the previous messages, we can listen for new ones:

this.chatService.listenForMessages(this.listenerId, msg => this.messages.push(msg));

We have a local property listnerId. With a value of ‘Web_App_Listener_Group_ID’, but you can use pretty much any value you want. This should be an unique value for our application, but since we have only one listener, we’re safe. As a method, we pass a function that will take any new message and add it to our messages array. Again, this will trigger the component to be rendered and we’ll see new messages on the screen.

It’s a good practice to remove message listeners when they are no longer needed. So let’s do that.

In our CometChat service we add the remove method:

removeListener(listenerId: string) {
  CometChat.removeMessageListener(listenerId);
}


And in our group view component, we add a handler for the destroy event and call it there:

ngOnDestroy(): void {
  this.chatService.removeListener(this.listenerId);
}


Adding new messages

The last part we need to do is write new messages and send them to the server.

First, we need to update the template with an input and button for this:


  
  
    Send
  



When the user clicks the ‘Send’ button, we take the text from the input and call the sendMessage method on our class. As a bonus we also clear the input value, to allow the user to write a new message.

To send the message we have to use the, you guessed it, sendMessage function. Before we send the message we have to create it:

const message = new CometChat.TextMessage(
  receiverId,
  text,
  CometChat.MESSAGE_TYPE.TEXT,
  CometChat.RECEIVER_TYPE.GROUP
);


This is an example of how to send text messages. The first value, receiverId, is the user or group id of whom we want to send the message to. Second, and the easiest one, is the text content of the message.

The third one is the type of the message, in our case, text. It can also be file, image, video or audio.

The last value represents the type of receiver, either a user or a group. In our case a group.

Once we have the message created, we send it to the server:

CometChat.sendMessage(message);

This was the sendMessage function, implemented inside the CometChat service class. You can have a look at the code here.

With this function in place we can go to our group view component and implement the sendMessage function there:

sendMessage(message: string) {
  this.chatService.sendMessage('supergroup', message);
}


One thing to keep in mind. The messages the user is sending will not get back into the message listener that we’ve registered. To see them on the screen after they are sent we have to manually add them to the messages array:

this.messages.push({
  text: message,
  sender: { uid: this.currentUser.uid }
});


That was it! Now we can receive and send messages in our super group 🙂.

Conclusion

This was a way to create a generic anonymous chat application with Angular and CometChat. You’ve went through the basics of using CometChat in an Angular context. Now can build on this and extend your application with new and cool capabilities.

Group screen with messages

The sample code on GitHub contains a bit more error handling and some basic css to make everything a bit more tidy. Don’t hesitate to check it out 😉.

Things to know before getting your own chatbot- Custom Chatbot Development

Things to know before getting your own chatbot- Custom Chatbot Development

This article gives you complete information on custom chatbots. We provide a complete understanding on chatbots and show a comparative analysis between platform chatbot and custom chatbot development

This article gives you complete information on custom chatbots. We provide a complete understanding on chatbots and show a comparative analysis between platform chatbot and custom chatbot development with its benefits.

How to Use Cookies in Angular for Storing user’s Credentials

How to Use Cookies in Angular for Storing user’s Credentials

In this post, I will be explaining about using Cookies in Angular for Storing user’s Credentials

By using cookies we are going to store the user's login data, if the user's credentials are valid, then it will be directed to the Dashboard page.

In this post, I will be explaining about Angular cookies. So what is a cookie? Cookies are like a small package of information that is stored by the user’s browser. Cookies persist across multiple requests and browser sessions that should be set so that they can be a great method for authentication in web applications. Sometimes we will have some queries about which is to be used -- either local storage or cookies? Before that, I like to say that the cookies and local storage serve different purposes.

The local storage can be read on the client-side, whereas the cookies are being read on the server-side. The biggest difference is the data size is about to store, the local storage will give more space to store, whereas the cookie is limited by the size of to store.

As I said above the cookies are used on the server-side whereas the local storage is used on the client-side. The local storage is a way of storing the data in the client’s PC, by saving the key/ value pair in a web browser with no expiration date. We will discuss about using local storage in the next article, so coming to the point, as I said the cookies are a kind of small file that are stored on the user’s browser.

The cookie is a small table which will contain key and data values so, by using this it will be very useful to carry information from one session to another session. Once we are about to store data on the server without using cookies then it will be difficult to retrieve a particular user’s information without a login on each visit to that website.

So far we have seen about the overview of a cookie and the usage of it. Now in this article, I will explain about storing the username and password of a static user in the cookie table. So, I have created two components, namely the login component and dashboard component, and I have set a static username and password in authservice.ts file.

So, when a user logs in to the login form by providing his user’s credentials the authservice checks the input and redirects the user to the dashboard if the user’s credentials are valid. If the user’s credentials are not valid it will alert by throwing enter valid email or password. And if the dashboard page is being accessed by unauthorized usage the page will be redirected to the login page automatically.

Setting up

In order to use cookies in Angular, we need to install the Angular cookie library by using the following npm package manager.

npm install ngx-cookie-service –save

After installing the package manager, we need to import the cookie service in the inside of our modules.

I have used the ng zorro library UI for form design, and you can find more information about ng zorro from the following link. The next step is to design a login form. So, open login.component.html file and replace the following code.

<form fxFill #Login="ngForm" (ngSubmit)="onsubmit()">  
    <div nz-row>  
        <div nz-col nzMd="12" nzXs="24">  
            <hr />  
            <nz-form-item>  
                <nz-input-group>  
                    <div nz-col nzMd="11" nzXs="8">  
                        <nz-input-group nzPrefixIcon="user">  
                            <input type="text" nz-input name="Login_name" placeholder="User Name" id="userName"  
 
#userName="ngModel" [(ngModel)]="Obj.username">  
                            </nz-input-group>  
                            <div *ngIf="Login.submitted && userName.errors" style="color: red">  
                                <div *ngIf="userName.hasError('required')">  
  
Login ID is required  
  
</div>  
                            </div>  
                        </div>  
                    </nz-input-group>  
                </nz-form-item>  
                <nz-form-item>  
                    <div nz-col nzMd="11" nzXs="8">  
                        <nz-input-group nzPrefixIcon="lock">  
                            <input type="password" nz-input name="user_password" placeholder="Password"  
  
id="password" #password="ngModel" [(ngModel)]="Obj.password">  
                            </nz-input-group>  
                            <div *ngIf="Login.submitted && password.errors" style="color: red">  
                                <div *ngIf="password.hasError('required')">  
  
Password is required  
  
</div>  
                            </div>  
                        </div>  
                    </nz-form-item>  
                    <div class="button">  
                        <button nz-button nzType="primary">  
  
submit  
  
</button>  
                    </div>  
                </div>  
            </div>  
        </form>  

Now open login.component.ts file and replace the following code in it.

import {  
    Component,  
    OnInit  
} from '@angular/core';  
import {  
    FormGroup  
} from '@angular/forms';  
import {  
    AuthService,  
    User  
} from '../services/authservice.service';  
import {  
    Router,  
    ActivatedRoute  
} from '@angular/router';  
import {  
    CookieService  
} from 'ngx-cookie-service';  
@Component({  
    selector: 'nz-demo-card-simple',  
    templateUrl: './login.component.html'  
})  
export class LoginComponent implements OnInit {  
    Obj: User;  
    constructor(private srvLogin: AuthService, private router: Router, public activatedRoute: ActivatedRoute, private cookieService: CookieService) {  
        this.Obj = new User();  
    }  
    ngOnInit(): void {}  
    onsubmit(): void {  
        this.cookieService.set('username', this.Obj.username);  
        this.cookieService.set('password', this.Obj.password);  
        console.log(this.cookieService.get('username'));  
        console.log(this.cookieService.get('password'));  
        const a = this.Obj;  
        if (this.srvLogin.checkLogValues(this.Obj)) {  
            this.srvLogin.isloggedin = true;  
            console.log(this.srvLogin.isloggedin);  
            this.router.navigate(['/dashboard']);  
        }  
    }  
}  

The next point is to create an authentication service, we can create a service file by using the syntax.

ng generate service AuthService

The service name which I have given is Authservice and the service will be created and I have provided a default static username and password in service file so that the validation will be executed and redirected to another page (dashboard page) if the user’s credentials are being valid. Open Authservice service.ts file and replace the following code and import it in both service and as well in app-module.ts file.

import {  
    Injectable  
} from '@angular/core';  
import {  
    HttpClient  
} from '@angular/common/http';  
import {  
    CookieService  
} from 'ngx-cookie-service';  
@Injectable({  
    providedIn: 'root'  
})  
export class AuthService {  
    private username = 'vidya';  
    private password = '123456';  
    isloggedin = false;  
    constructor(private http: HttpClient) {}  
    checkLogValues(value: User): boolean {  
        if (this.username === value.username && this.password === value.password) {  
            console.log(this.username);  
            console.log(this.password);  
            // alert('Login valid');  
            return true;  
        } else {  
            alert('please enter valid data');  
            return false;  
        }  
    }  
}  
export class User {  
    username: string;  
    password: string;  
}  

After that create a component named as dashboard and open dashboard.component.html file and replace the following code.

<h3>Hello {{userDisplayName}} you are in Dashboard </h3>  
<div style="text-align:right">  
   <button nz-button nzType="danger" (click)="logout()">Logout</button>  
</div>  

The next step is to open dashboard.component.ts file and replace the following code inside it.

import {  
    Component,  
    OnInit  
} from '@angular/core';  
import {  
    AuthService,  
    User  
} from '../services/authservice.service';  
import {  
    Router,  
    ActivatedRoute  
} from '@angular/router';  
import {  
    CookieService  
} from 'ngx-cookie-service';  
@Component({  
    selector: 'dashboard',  
    templateUrl: './dashboard.component.html'  
})  
export class DashboardComponent implements OnInit {  
    Obj: User;  
    [x: string]: any;  
    userDisplayName = '';  
    password = '';  
    constructor(private srvLogin: AuthService, private router: Router, public activatedRoute: ActivatedRoute, private cookieService: CookieService) {  
        this.Obj = new User();  
        this.userDisplayName = this.cookieService.get('username');  
        this.password = this.cookieService.get('password');  
        this.Obj.username = this.userDisplayName;  
        this.Obj.password = this.password;  
        if (!srvLogin.checkLogValues(this.Obj)) {  
            router.navigate(['/login']);  
        }  
    }  
    ngOnInit(): void {}  
    logout(): void {  
        this.router.navigate(['/login']);  
        this.cookieService.deleteAll();  
    }  
}  

The following next step is to log in to the dashboard by providing the user’s credentials and after the valid login, we can see the user’s name in dashboard as a welcome note by using the user’s login name. So, after entering into the dashboard page open the developer’s tool in the browser and navigate -> Application and select cookies from storage. So, on that, we can see the user name and password have been stored in the cookie table.

So  far we have seen about storing the user’s details in the cookie table and now we can take an overview on clearing the cookies in the cookie table; for that use deleteall() method for clearing the cookies table if  the user is about to click-> logout button.

Conclusion

In this post, we have seen about using cookies in Angular for storing user’s credentials. I hope this article will be useful for you.

Angular Tutorial - Learn Angular from Scratch

Angular Tutorial - Learn Angular from Scratch

Angular Tutorial - Learn Angular from Scratch: This course is for beginners who are curious on how to get started with Angular. In this course you will learn how to download, install and play around with Angular. We teach you the main components of Angular, so that you can get up and running with it asap. You will learn now to start building applications with Angular.

This course is for beginners who are curious on how to get started with Angular. In this course you will learn how to download, install and play around with Angular. We teach you the main components of Angular, so that you can get up and running with it asap. You will learn now to start building applications with Angular.

Learning Angular can be a daunting experience that's why this course was created; to give you an easier learning experience with it.

What am I going to get from this course?

  • You will learn the mayor fundamentals of Angular
  • You will learn how to get up and running with Angular
  • You will learn to create Applications using Angular 5 and beyond

What you'll learn

  • You will learn the mayor fundamentals of Angular
  • You will learn how to get up and running with Angular
  • You will learn to create Applications using Angular 5 and beyond