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.
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:
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
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:
- The Header (
- The Drawer (
- The Page Container (
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.
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.tsfile 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
/home route is not defined, so that results in a 404 error.
Structuring (Quasar) Pages
ui/pages/Index.vue (snapshot) file contains a template which wraps a
q-page component. The
q-page component wraps 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.