-
Notifications
You must be signed in to change notification settings - Fork 25
Ionic Chat Screen
After we've implemented the elastic-textarea
and chat-bubble
components, it's time to use those new components and create our ionic2 Chat page.
As always, we'll create a chatPage directory in our app/pages project folder, and we'll create the 3 required files: chatPage.html, chatPage.js, and chatPage.scss.
Below you can see the content of the chatPage.html
<ion-navbar *navbar primary>
<ion-title>
{{contactName}}
</ion-title>
</ion-navbar>
<ion-content #content padding class="chatPage">
<ion-list no-lines>
<ion-item *ngFor="let msg of messages" >
<chat-bubble [message]="msg"></chat-bubble>
</ion-item>
</ion-list>
</ion-content>
<ion-footer class="chatPageFooter">
<ion-toolbar>
<ion-item>
<ion-label style="margin:0px;"></ion-label>
<div item-content style="width:100%;">
<elastic-textarea #txtChat placeholder="Type to compose" lineHeight="22"></elastic-textarea>
</div>
</ion-item>
<ion-buttons right>
<button style="min-width:45px;" (click)="sendMessage()">
<ion-icon name="send"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
</ion-footer>
Important things to point out in this view is that we are marking the <ion-content>
component with an id #content
because we want to reference it later on in the controller.
Inside the ion-list
we are rendering a list of our chat-bubble
components that we previously defined.
We are using the ion-footer
to stick the input part of the page - the elastic-textarea
and the button - to the bottom of the screen.
A Toolbar is a generic bar that is positioned above or below content. Unlike a Navbar, a toolbar can be used as a subheader. When toolbars are placed within an <ion-header>
or <ion-footer>
, the toolbars stay fixed in their respective location. When placed within <ion-content>
, toolbars will scroll with the content. More on toolbars in official ionic2 documentation.
Using the ion-navbar
at the top of the page, we automatically get the back
button in our navigation bar, which is added by the ion-nav
component that we already instantiated in our app.html. The back
button gets added if there is a page before the one you are navigating to in the navigation stack.
The chatPage.scss is rather simple in this case. You can see it below.
.chatPage {
ion-label {
margin: 0px 8px 13px 0;
}
}
.chatPageFooter {
.toolbar-background {
background: map-get($colors, background-color);
}
}
We are just adjusting the ion-label
margins because chat-bubbles
are wrapped inside ion-label
when ion-item
is rendered.
Let's see the code and then we'll cover the interesting bits.
import {Component, ViewChild} from '@angular/core';
import {NavController, NavParams} from 'ionic-angular';
import {ChatBubble} from '../components/chatBubble/chatBubble';
import {ElasticTextarea} from '../components/elasticTextarea';
@Component({
templateUrl: 'build/pages/chatPage/chatPage.html',
directives: [ChatBubble, ElasticTextarea],
queries: {
txtChat: new ViewChild('txtChat'),
content: new ViewChild('content')
}
})
export class ChatPage {
static get parameters() {
return [[NavController], [NavParams]];
}
constructor(nav, navParams) {
this.nav = nav;
this.navParams = navParams;
this.contactName = this.navParams.get('contactName');
this.messages = [
{
img: 'build/img/hugh.png',
position: 'left',
content: 'Hello from the other side.',
senderName: 'Gregory',
time: '28-Jun-2016 21:53'
},
{
img: 'build/img/hugh.png',
position: 'right',
content: 'Hi! How are?',
senderName: 'Me',
time: '28-Jun-2016 21:55'
},
{
img: 'build/img/hugh.png',
position: 'left',
content: "This is some really long test that I'm writing here. Let's see how it wraps.",
senderName: 'Gregory',
time: '28-Jun-2016 21:57'
}
];
}
sendMessage(){
this.txtChat.setFocus();
this.messages.push({
img: 'build/img/hugh.png',
position: 'right',
content: this.txtChat.content,
senderName: 'Me',
time: new Date().toLocaleTimeString()
});
this.txtChat.clearInput();
setTimeout(() => {
this.content.scrollToBottom(300);//300ms animation speed
});
}
}
An interesting thing to point out here is our first use of NavParameters
. We are injecting NavParameters
and are then using it in the component's constructor to obtain the contactName
:
this.navParams.get('contactName')
This code works because we have set this parameter with this exact key when we were navigating to the ChatPage
from our ContactPage
using the following code:
this.nav.push(ChatPage, {contactName: "Dr. Gregory House"});
In our sendMessage()
method we are pushing the new message to the messages
array, we are also clearing the input with this.txtChat.clearInput()
, but we are also scrolling our view to the last message (chat bubble) that was added to it. Here's the code for that bit:
setTimeout(() => {
this.content.scrollToBottom(300);//300ms animation speed
});
We had to use setTimout(..)
in this case because without it our view would only scroll to the second to last element in the view. Seems like the issue was that the scrolling was occurring prior to the new chat message being added to the view. setTimout(..)
solved this issue
It definitely seemed simpler and quicker to create the Chat Screen in Android Native then it was in Ionic2. However, I'm contributing that to the maturity of Android platform, and the pure amount of ready made examples that are available for it. I did managed to find some good resources for Ionic implementation of the same screen, however, they were for the version 1 of the Ionic, and I had to put in some good work to adjust them so I would be able to use them.
After all was said and done, I would give a small advantage to Android Native in this particular scenario, but I also love the fact that I'm able to design this screen with pure code (HTML5, CSS, and Javascript) in Ionic2, without having to worry about creating custom images and resources like I did in Android Native.
- https://ionicframework.com/docs/v2/api/components/nav/Nav/
- https://ionicframework.com/docs/v2/api/components/nav/NavController/
- https://ionicframework.com/docs/v2/api/components/toolbar/Toolbar/
- https://github.com/smukov/AvI/commit/9eca804c894244f47fe07277586d65f434e4df9e
- https://github.com/smukov/AvI/commit/51a4b482430b3abedf9727aa1f75bc5ad150f557
- https://github.com/smukov/AvI/commit/d3e13781e7eece2343ba54df27da0ec415b984b4
- https://github.com/smukov/AvI/commit/741f64e092adf148b511afeb1b64417eed967c5e
- https://github.com/smukov/AvI/commit/28aea168aa0cec2b15f182ad23726134dc73b84c
- https://github.com/smukov/AvI/commit/d45845a242b03d16d42d6ae221360a678da184ae
- improved chat page, input doesn't lose focus and keyboard stays app on send
- Android
- Getting Started
- Project Structure
- Gradle
- Menu
- Theming
- Login Screen
- Menu & Navigation
- Importing Library From GitHub
- Creating Reusable Layouts
- Adding New Icons
- Profile Screen
- Chat Screen
- Contacts Screen
- Pending Invites Screen
- Settings Screen
- Add Library Dependency
- Discover Users Screen
- Splash Screen
- Auth0
- Authentication Logic
- Profile Screen Logic
- Send Feedback
- Authenticated to Firebase via Auth0
- Saving User Info to Firebase
- Storing User Connection Info to Firebase
- Calculating Distance Between Users
- Chat Logic
- Handling Device Rotation
- Android Other
- Ionic
- Getting Started
- Project Structure
- Menu
- Theming
- Login Screen
- Adding Images
- Creating Reusable Layouts
- Adding New Icons
- Profile Screen
- Contact Screen
- Elastic Textarea
- Chat Bubble
- Chat Screen
- Contacts Screen
- Pending Invites Screen
- Settings Screen
- Discover Users Screen
- Splash Screen
- Animations
- Auth0
- Storing User Data
- Profile Screen Logic
- Send Feedback
- Update to Ionic RC0
- Reimplemented Auth0 with Ionic RC0
- Authenticated to Firebase via Auth0
- Saving User Info to Firebase
- Storing User Connection Info to Firebase
- Calculating Distance Between Users
- Chat Logic
- Handling Device Rotation
- Ionic Other
- Version Updating
- Cordova
- Other
- Messaging