Frontend Overview | Full-Stack Google Contacts Clone with Adonis.js/Node.js and Quasar (Vue.js)

Frontend Overview | Full-Stack Google Contacts Clone with Adonis.js/Node.js and Quasar (Vue.js)

In this lesson, you will gain a deeper understanding of how a Quasar UI is structured.

It is recommended that you read all layout-related pages on the official docs: Layout, Layout Header and Footer, Layout Drawer, Layout Page, Page Sticky, etc.

A Quasar UI project has a familiar structure for those who have used other Vue.js frameworks such as Nuxt. All code-related files you will be editing and creating are stored in ui/src folder. A full breakdown of the directories under ui can be found at: quasar.dev/quasar-cli/directory-structure.

You will begin by editing the content of the left drawer which can be toggled by clicking the menu button on the top-left corner of the window. It currently contains some placeholders. We want it to look like the image below:

google-contacts-clone-target-left-drawer.png

Quasar Config

An important note to add is that the series will make use of material icons. You can them here. This is the default choice by the Quasar Framework. You can change to your own icon set in the file: ui/quasar.conf.js. This file is executed by the Quasar CLI in the Node.js environment, so you must have Node.js installed. You can read more about installing and using extra fonts and icons here. You are read more about the configurations with the ui/quasar.conf.jg here.

Deep Dive into the (Quasar) Layout

The layout of the UI can be found in the ui/src/layouts/MainLayout.vue SFC (single-file component) file. The snapshot of the file at this point is found here. The template within the file starts with a q-layout component which wraps the entire template. Within the q-layout component are three important sections:

  1. The Header (q-header),
  2. The Drawer (q-drawer), and
  3. The Page Container (q-page-container).

The q-header component forms the top header of the layout. It will be constant for all views using this layout. It contains the toolbar (q-toolbar) which contains all the components you can see in the header. Look around and you will be logo, search input, and dropdown.

The q-drawer component forms the left drawer for the application. It is also constant for all views. Our drawer customisation will be done within this component.

The Page Container is equally very important. It determines all the content which will appear within the body of the layout. It also allows all the router views we want to display to be possible. That is why you see the router-view component within the q-page-container component. Typically, an application could have nested router-view components but there must be one at the top-level in the layout file as the entry point.

There is an example component displayed dead center without the page container. It shows a list of todo tasks (ct1 to ct5), count, active, and clicks on todos. If you click on any todo task, the clicks on todo will be incremented by 1. Where does it come from? It comes from the router-view component. How is this possible? The router-view is used to load any component which as assigned to the current route. In this case, the current route is / i.e. the entry route. You can see which component was assigned to the / route by examining the routes configuration in the router index file. Navigate to ui/router/index.ts. The snapshot of the index file at this point can be found here.

More Gist About Vue Router and Routes

The router index file contains all configuration for Vue Router which is responsible for all navigations without the app. The line import routes from "./routes"; imports the routes declaration into the index file. Navigate to ui/router/routes.ts. The snapshot of this file at this point is found here. The route.ts file exports an array of route objects. There are currently two route objects. One with the path "/" and a catchAll route used for detecting 404 errors within your frontend navigations. Let's call the "/" path the home route going forward. The home route defines the the ui/layouts/MainLayout.vue layout file as the route component. This is how the MainLayout.vue is loaded for the first time, enabling the rendering of the entire layout of the application as described in the previously. Without this, our entire app will break. A route object call contain children route objects. Obviously, since this is the home route, the children route object will be used to load every other component into the app. In Vue Router, you can nest your route objects as deep as your application requires. You can see a demonstration in the route file of the Akpoho Invoicing Software.

The children property of the home route contains one route object. This route object defines a path, "". The path is empty. Why? In Vue Router, when you define a path as empty, it implies that you want the component define in the route to appear when the path of the parent route is navigated to. In this case, the parent route path is /, so the the component file, ui/pages/Index.vue, defined for this route will be loaded to replace the router-view component when you visit the path /. Snapshot of ui/pages/Index.vue at this point. This will become clearer soon. Also study the route file of the Akpoho Invoicing Software for lots of such implementations.

TIP: In a large app, your route.ts file can easily grow so long and difficult to navigate. Since it is a regular JavaScript file, you can group and extract some route objects into separate files and import them into the main route.ts file as done here.

Now, navigate to the ui/pages/Index.vue file and you will see the component responsible for the example component currently displayed in the center of the layout. This component will be replaced with a table for listing your contacts as seen in the home page of the desktop view of contacts.google.com.

I mentioned that the routes.ts file has a single route object for catching 404 errors. You should not remove that route object and it should always be the last because Vue Router will search through all our routes to find a match for the page you intend to visit. The moment Vue Router arrives at this route, /:catchAll(.*)*, it means that the page you intend navigating to is unavailable. The router will load the component file ui/pages/Error404.vue to show the 404 error page. Try it out by entering http://localhost:8008/#/home. The /home route is not defined, so that results in a 404 error.

Structuring (Quasar) Pages

The ui/pages/Index.vue (snapshot) file contains a template which wraps a q-page component. The q-page component wraps the example-component. The q-page component from Quasar is used to define a new page. It indicates the beginning of the new page. Because of this, it should be the root component for every component file used for defining a page. When loaded via the router-view, it is become the direct child of the q-page-container. Read more here.

// From https://quasar.dev/layout/page#usage

<q-layout>
  ...
  <q-page-container>
    <q-page>
      <!-- page content -->
    </q-page>
  </q-page-container>
  ...
</q-layout>

In the next lesson, you will start the actual customisation of the UI beginning from the left drawer component.