Skip to main content

Vue.js Quasar Framework

Introduction

Quasar is a powerful Vue.js UI framework that allows developers to build high-performance web applications, progressive web apps (PWAs), mobile applications (using Cordova or Capacitor), and even desktop applications (using Electron) from a single codebase. Built on top of Vue.js, Quasar provides a rich set of components, directives, and utilities that accelerate development while maintaining excellent performance.

In this guide, we'll explore what makes Quasar special, how to get started with it, and how to leverage some of its powerful components in real-world applications.

Why Choose Quasar?

Quasar stands out among Vue UI frameworks for several reasons:

  1. One codebase, multiple platforms - Write once, deploy everywhere (web, mobile, desktop)
  2. Performance-focused - Highly optimized components with minimal bundle size
  3. Comprehensive component library - Over 100+ pre-built Vue components
  4. Material Design and iOS themes - Built-in support for different design systems
  5. Active community and development - Regular updates and improvements

Getting Started with Quasar

Installation

Let's start by setting up a new Quasar project:

bash
# Install Quasar CLI globally
npm install -g @quasar/cli

# Create a new project
quasar create my-quasar-project

# Navigate to project folder
cd my-quasar-project

# Start the development server
quasar dev

This will create a new Quasar project with the default structure and launch a development server.

Project Structure

A typical Quasar project has the following structure:

my-quasar-project/
├── .quasar/ # Generated files (don't edit)
├── node_modules/ # Dependencies
├── public/ # Public static assets
├── src/ # Your application code
│ ├── assets/ # App assets (processed by webpack)
│ ├── boot/ # App initialization code
│ ├── components/ # Vue components
│ ├── css/ # CSS/Stylus/SASS/etc files
│ ├── layouts/ # Layout components
│ ├── pages/ # Page components
│ ├── router/ # Vue Router configuration
│ ├── store/ # Vuex Store files
│ ├── App.vue # Root Vue component
│ └── index.template.html # Template for index.html
├── package.json # Project dependencies and scripts
└── quasar.conf.js # Quasar configuration file

Basic Configuration

The quasar.conf.js file is central to your Quasar application. It allows you to configure various aspects of your app:

javascript
module.exports = function (ctx) {
return {
// Which Quasar components/directives to import
framework: {
components: [
'QLayout',
'QHeader',
'QDrawer',
'QPageContainer',
'QPage',
'QToolbar',
'QToolbarTitle',
'QBtn',
'QIcon',
'QList',
'QItem',
'QItemSection',
'QItemLabel'
],
directives: [
'Ripple'
],
plugins: [
'Notify'
]
},

// Enable auto-import of components
extras: [
'material-icons'
],

// Build configuration
build: {
vueRouterMode: 'history'
}
}
}

Core Quasar Components

Layout System

Quasar's layout system helps you create responsive interfaces. Here's a basic layout example:

html
<template>
<q-layout view="hHh lpR fFf">
<!-- Header -->
<q-header elevated class="bg-primary text-white">
<q-toolbar>
<q-btn flat dense round icon="menu" @click="drawer = !drawer" />
<q-toolbar-title>Quasar App</q-toolbar-title>
</q-toolbar>
</q-header>

<!-- Drawer / Sidebar -->
<q-drawer v-model="drawer" show-if-above bordered>
<q-list>
<q-item-label header>Navigation</q-item-label>
<q-item clickable to="/" exact>
<q-item-section avatar>
<q-icon name="home" />
</q-item-section>
<q-item-section>Home</q-item-section>
</q-item>
<q-item clickable to="/about" exact>
<q-item-section avatar>
<q-icon name="info" />
</q-item-section>
<q-item-section>About</q-item-section>
</q-item>
</q-list>
</q-drawer>

<!-- Page content -->
<q-page-container>
<router-view />
</q-page-container>
</q-layout>
</template>

<script>
export default {
data() {
return {
drawer: false
}
}
}
</script>

This layout includes a header with a toolbar, a drawer (sidebar) that can be toggled, and a container for page content.

Form Components

Quasar provides numerous form components. Here's an example of a login form:

html
<template>
<q-page padding>
<q-card class="login-card">
<q-card-section class="bg-primary text-white">
<h4 class="q-ma-none">Login</h4>
</q-card-section>

<q-card-section>
<q-form @submit="onSubmit" class="q-gutter-md">
<q-input
v-model="email"
label="Email"
type="email"
:rules="[val => !!val || 'Email is required']"
/>

<q-input
v-model="password"
label="Password"
type="password"
:rules="[val => !!val || 'Password is required']"
/>

<q-toggle v-model="rememberMe" label="Remember Me" />

<div>
<q-btn label="Submit" type="submit" color="primary" />
<q-btn label="Reset" type="reset" color="primary" flat class="q-ml-sm" />
</div>
</q-form>
</q-card-section>
</q-card>
</q-page>
</template>

<script>
export default {
data() {
return {
email: '',
password: '',
rememberMe: false
}
},
methods: {
onSubmit() {
this.$q.notify({
color: 'green-4',
textColor: 'white',
icon: 'cloud_done',
message: 'Submitted'
})
}
}
}
</script>

<style lang="scss" scoped>
.login-card {
max-width: 500px;
margin: 0 auto;
}
</style>

Table Component

Quasar's table component is feature-rich and flexible:

html
<template>
<div class="q-pa-md">
<q-table
title="Users"
:data="data"
:columns="columns"
row-key="id"
:pagination.sync="pagination"
>
<template v-slot:body="props">
<q-tr :props="props">
<q-td key="id" :props="props">{{ props.row.id }}</q-td>
<q-td key="name" :props="props">{{ props.row.name }}</q-td>
<q-td key="email" :props="props">{{ props.row.email }}</q-td>
<q-td key="actions" :props="props">
<q-btn size="sm" color="info" icon="edit" @click="editUser(props.row)" />
<q-btn size="sm" color="negative" icon="delete" @click="deleteUser(props.row)" class="q-ml-sm" />
</q-td>
</q-tr>
</template>
</q-table>
</div>
</template>

<script>
export default {
data() {
return {
pagination: {
rowsPerPage: 10
},
columns: [
{ name: 'id', required: true, label: 'ID', align: 'left', field: 'id', sortable: true },
{ name: 'name', required: true, label: 'Name', align: 'left', field: 'name', sortable: true },
{ name: 'email', required: true, label: 'Email', align: 'left', field: 'email', sortable: true },
{ name: 'actions', required: true, label: 'Actions', align: 'center', field: 'actions' }
],
data: [
{ id: 1, name: 'John Doe', email: '[email protected]' },
{ id: 2, name: 'Jane Smith', email: '[email protected]' },
{ id: 3, name: 'Bob Johnson', email: '[email protected]' }
]
}
},
methods: {
editUser(user) {
this.$q.notify({
message: `Editing user: ${user.name}`,
color: 'info'
})
},
deleteUser(user) {
this.$q.notify({
message: `Deleting user: ${user.name}`,
color: 'negative'
})
}
}
}
</script>

Practical Example: Building a Todo App

Let's build a simple Todo application to demonstrate how Quasar components work together:

html
<template>
<q-page padding>
<div class="q-pa-md" style="max-width: 500px; margin: 0 auto;">
<h4 class="text-h4 q-mb-md">Todo List</h4>

<!-- Add new todo -->
<q-form @submit="addTodo" class="q-mb-md">
<div class="row q-col-gutter-sm">
<div class="col">
<q-input
v-model="newTodo"
label="New task"
dense
:rules="[val => !!val || 'Task is required']"
/>
</div>
<div class="col-auto">
<q-btn
label="Add"
type="submit"
color="primary"
icon="add"
:disable="!newTodo"
/>
</div>
</div>
</q-form>

<!-- Todo list -->
<q-list bordered separator>
<q-item v-for="(todo, index) in todos" :key="index" :class="{ 'done': todo.completed }">
<q-item-section avatar>
<q-checkbox v-model="todo.completed" />
</q-item-section>

<q-item-section>
<q-item-label :class="{ 'text-strike': todo.completed }">
{{ todo.text }}
</q-item-label>
</q-item-section>

<q-item-section side>
<q-btn flat round color="negative" icon="delete" @click="removeTodo(index)" />
</q-item-section>
</q-item>

<q-item v-if="todos.length === 0">
<q-item-section class="text-grey text-center">
No tasks yet. Add a new one!
</q-item-section>
</q-item>
</q-list>

<!-- Statistics -->
<div class="q-mt-md">
<q-badge color="primary" class="q-mr-sm">
Total: {{ todos.length }}
</q-badge>
<q-badge color="positive" class="q-mr-sm">
Completed: {{ completedCount }}
</q-badge>
<q-badge color="negative">
Pending: {{ pendingCount }}
</q-badge>
</div>
</div>
</q-page>
</template>

<script>
export default {
data() {
return {
newTodo: '',
todos: [
{ text: 'Learn Quasar', completed: false },
{ text: 'Build an app', completed: false }
]
}
},
computed: {
completedCount() {
return this.todos.filter(todo => todo.completed).length
},
pendingCount() {
return this.todos.length - this.completedCount
}
},
methods: {
addTodo() {
if (this.newTodo.trim()) {
this.todos.push({
text: this.newTodo,
completed: false
})
this.newTodo = ''

this.$q.notify({
message: 'Task added!',
color: 'positive',
icon: 'check'
})
}
},
removeTodo(index) {
this.$q.dialog({
title: 'Confirm',
message: 'Are you sure you want to delete this task?',
cancel: true,
persistent: true
}).onOk(() => {
this.todos.splice(index, 1)
this.$q.notify({
message: 'Task removed!',
color: 'negative',
icon: 'delete'
})
})
}
}
}
</script>

<style lang="scss" scoped>
.done {
background-color: rgba(0, 0, 0, 0.03);
}
</style>

This example demonstrates several Quasar components working together:

  • q-form and q-input for form handling
  • q-list and q-item for displaying todos
  • q-checkbox for marking todos as completed
  • q-btn for actions
  • q-badge for statistics
  • Quasar's notification and dialog plugins

Advanced Features

Quasar Plugins

Quasar offers various plugins that extend functionality. Here's how to use the Dialog plugin:

html
<template>
<div class="q-pa-md">
<q-btn color="primary" label="Show Dialog" @click="showDialog" />
</div>
</template>

<script>
export default {
methods: {
showDialog() {
this.$q.dialog({
title: 'Alert',
message: 'This is an example of Quasar Dialog',
persistent: true,
ok: {
color: 'primary',
label: 'OK'
}
}).onOk(() => {
this.$q.notify('You clicked OK!')
})
}
}
}
</script>

Responsive Design

Quasar includes a powerful responsive system built on Flexbox:

html
<template>
<div class="q-pa-md">
<div class="row q-col-gutter-md">
<!-- This column will be 12 cols on xs, 6 on sm, 4 on md and up -->
<div class="col-12 col-sm-6 col-md-4">
<q-card class="full-height">
<q-card-section>
<div class="text-h6">Card 1</div>
</q-card-section>
<q-card-section>
Content adjusts based on screen size
</q-card-section>
</q-card>
</div>

<div class="col-12 col-sm-6 col-md-4">
<q-card class="full-height">
<q-card-section>
<div class="text-h6">Card 2</div>
</q-card-section>
<q-card-section>
Responsive layout
</q-card-section>
</q-card>
</div>

<div class="col-12 col-sm-12 col-md-4">
<q-card class="full-height">
<q-card-section>
<div class="text-h6">Card 3</div>
</q-card-section>
<q-card-section>
Using Quasar classes
</q-card-section>
</q-card>
</div>
</div>
</div>
</template>

Theme Customization

You can customize Quasar's theme using SCSS variables. Create a src/css/quasar.variables.scss file:

scss
// src/css/quasar.variables.scss
$primary : #1976D2;
$secondary : #26A69A;
$accent : #9C27B0;

$dark : #1D1D1D;

$positive : #21BA45;
$negative : #C10015;
$info : #31CCEC;
$warning : #F2C037;

Then, update your quasar.conf.js to use these variables:

javascript
module.exports = function (ctx) {
return {
// ...other config
css: [
'app.scss'
],
// ...other config
}
}

And finally, create src/css/app.scss:

scss
// src/css/app.scss
@import './quasar.variables.scss';

// Add any additional custom styles here
.custom-component {
background: $primary;
color: white;
}

Building for Multiple Platforms

One of Quasar's most powerful features is its ability to build for multiple platforms.

Progressive Web App (PWA)

bash
# Install PWA mode
quasar mode add pwa

# Build for production
quasar build -m pwa

Mobile App (Capacitor)

bash
# Install Capacitor mode
quasar mode add capacitor

# Add platforms
quasar capacitor add android
quasar capacitor add ios

# Build and open in development
quasar dev -m capacitor -T android
quasar dev -m capacitor -T ios

Desktop App (Electron)

bash
# Install Electron mode
quasar mode add electron

# Run in development
quasar dev -m electron

# Build for production
quasar build -m electron

Summary

In this guide, we've explored Quasar Framework, a powerful Vue.js-based UI library that enables developers to build high-performance applications for multiple platforms from a single codebase. We've covered:

  • Setting up a Quasar project
  • Working with core components like layouts, forms, and tables
  • Building a practical Todo application
  • Using advanced features like plugins and responsive design
  • Customizing themes and styling
  • Building for multiple platforms

Quasar's comprehensive component library, excellent documentation, and cross-platform capabilities make it an excellent choice for Vue.js developers looking to build modern, responsive applications.

Additional Resources

To continue learning about Quasar:

  1. Official Documentation: Visit Quasar's official documentation for in-depth guides and API references.
  2. GitHub Repository: Explore the GitHub repository for source code and issues.
  3. Community: Join the Quasar Discord community for help and discussions.

Exercises

  1. Basic: Create a simple contact form using Quasar form components with validation.
  2. Intermediate: Build a responsive dashboard layout with charts using Quasar's layout system.
  3. Advanced: Create a full-featured note-taking app with local storage that can be deployed as both a PWA and a mobile app.

By exploring these exercises, you'll gain a deeper understanding of how Quasar components work together to create powerful applications.



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)