Lesson 10

Setting up the Basic User Interface

Creating the basic user interface for the application

PRO

Lesson Outline

Setting up the Basic User Interface

Our first goal is going to be to get the basic interface set up for the application, this means we will need to implement the following:

  • A notices page that displays a list of notices
  • An add notice page that allows for the creation of new notices
  • A chat page that displays a list of chats, and allows for the creation of new chats

We will be implementing a simple version to begin with that will not actually allow us to add data, we won't be worrying about integrating with PouchDB and CouchDB just yet. We also won't be worrying too much about the design or user experience just yet, our main focus is to get the bare bones interface in place.

Once we have that we can start getting into the specifics of CouchDB and PouchDB and how we can go about integrating that nicely into the architecture of our Ionic application. Then when we have the basics working how we want, we can circle back to improving the interface.

Set up Tabs

Since we didn't use the tabs starter we will need to do just a little bit of configuration to get our tabs up and running.

Modify src/app/home/home-routing.module.ts to reflect the following:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomePage } from './home.page';

const routes: Routes = [
  {
    path: 'tabs',
    component: HomePage,
    children: [
      {
        path: 'notices',
        children: [
          {
            path: '',
            loadChildren: () =>
              import('../notices/notices.module').then(
                (m) => m.NoticesPageModule
              ),
          },
        ],
      },
      {
        path: 'chat',
        children: [
          {
            path: '',
            loadChildren: () =>
              import('../chat/chat.module').then((m) => m.ChatPageModule),
          },
        ],
      },
    ],
  },
  {
    path: '',
    redirectTo: '/tabs/notices',
    pathMatch: 'full',
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],
})
export class HomePageRoutingModule {}

We just have our Notices and Chat tabs defined here. Now we just need to add the Ionic tabs components to our home pages template.

Modify src/app/home/home.page.html to reflect the following:

<ion-tabs>
  <ion-tab-bar color="primary" slot="top">
    <ion-tab-button tab="notices">
      <ion-icon name="clipboard"></ion-icon>
    </ion-tab-button>

    <ion-tab-button tab="chat">
      <ion-icon name="chatbubbles"></ion-icon>
    </ion-tab-button>
  </ion-tab-bar>
</ion-tabs>

Notice that we have supplied slot="top" so that our tab bar will be displayed at the top of the application rather than the bottom. The reason we are doing this is because we will be adding a chat input at the bottom of the chat page, so the tab bar works better at the top in this instance. Users would expect a chat input to be at the bottom of the screen so it is a good idea to conform to this, but it is also easier to interact with elements closer to the bottom of the screen, and the user will likely interact with the chat input more than they do the tab bar.

Displaying Notices

The first tab is our notices page, and we will be implementing a card list on this page that will display all the notices. For now, we are just going to set up some dummy data in the constructor that we will replace with real data from CouchDB later.

So that we can give our notices an appropriate type, let's create an interface for it first.

Create a file at src/app/interfaces/notice.ts and add the following:

export interface Notice {
  title: string;
  message: string;
  author: string;
}

Since we will be launching a modal based on our AddNoticePage from our notices page, we will need to add the AddNoticePage as a declaration to the module for our notices page so that we can supply it to the ModalController. Let's do that now.

Modify src/app/notices/notices.module.ts to reflect the following:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { IonicModule } from '@ionic/angular';

import { NoticesPageRoutingModule } from './notices-routing.module';

import { NoticesPage } from './notices.page';
import { AddNoticePage } from '../add-notice/add-notice.page';

@NgModule({
  imports: [CommonModule, FormsModule, IonicModule, NoticesPageRoutingModule],
  declarations: [NoticesPage, AddNoticePage],
})
export class NoticesPageModule {}

Modify src/app/notices/notices.page.ts to reflect the following:

import { Component, OnInit } from '@angular/core';
import {
  AlertController,
  ModalController,
  ActionSheetController,
} from '@ionic/angular';
import { AddNoticePage } from '../add-notice/add-notice.page';
import { Notice } from '../interfaces/notice';

@Component({
  selector: 'app-notices',
  templateUrl: './notices.page.html',
  styleUrls: ['./notices.page.scss'],
})
export class NoticesPage implements OnInit {
  public notices: Notice[] = [];

  constructor(
    private alertCtrl: AlertController,
    private modalCtrl: ModalController,
    private actionSheetCtrl: ActionSheetController
  ) {}

  ngOnInit() {
    // Just some test notices for now
    this.notices = [
      { title: 'hello', message: 'this is a message', author: 'test' },
      { title: 'hello', message: 'this is a message', author: 'test' },
    ];
  }

  async openAddNoticePage(notice?: Notice): Promise<void> {
    const modal = await this.modalCtrl.create({
      component: AddNoticePage,
      componentProps: {
        notice: notice,
      },
    });

    modal.present();
  }

  async deleteNotice(notice: Notice): Promise<void> {
    const confirm = await this.alertCtrl.create({
      header: 'Delete this notice?',
      message: 'Deleting this notice will remove it permanently.',
      buttons: [
        {
          text: 'Delete',
          handler: () => {},
        },
        {
          text: 'Keep it',
        },
      ],
    });

    confirm.present();
  }

  async openNoticeActions(notice: Notice): Promise<void> {
    const actionSheet = await this.actionSheetCtrl.create({
      buttons: [
        {
          text: 'Edit',
          icon: 'create',
          handler: () => {
            this.openAddNoticePage(notice);
          },
        },
        {
          text: 'Delete',
          role: 'destructive',
          icon: 'trash',
          handler: () => {
            this.deleteNotice(notice);
          },
        },
        {
          text: 'Cancel',
          icon: 'close',
          role: 'cancel',
        },
      ],
    });

    actionSheet.present();
  }

  logout() {}
}

We've set up three main methods here: openAddNoticePage which will launch our page for adding notices as a modal, deleteNotice which will launch a confirmation message for deleting a notice (we will implement the actual deletion process later), and openNoticeActions which will open an action sheet allowing the user to select between the edit and delete options for a notice. We've also added a placeholder for a logout method that we will implement later.

Modify src/app/notices/notices.page.html to reflect the following:

PRO

Thanks for checking out the preview of this lesson!

The full version of this lesson is only available to pro members. If you would like full access to this module and all of the other pro modules on Elite Ionic you can become a pro member (or log in if you are already a member).