Skip to main content

Vue.js PrimeVue

Introduction

PrimeVue is a rich and comprehensive UI component library for Vue.js applications. Built on top of the popular PrimeFaces design, it offers a collection of over 90 flexible, feature-rich components that can accelerate your Vue development process significantly.

As a beginner learning Vue.js, incorporating a well-established UI library like PrimeVue will help you build professional-looking applications without having to create UI components from scratch. PrimeVue is specifically designed for Vue 3, but also supports Vue 2.

In this guide, we'll explore:

  • Setting up PrimeVue in your Vue.js project
  • Core PrimeVue components and their usage
  • Styling and theming options
  • Building a practical application with PrimeVue

Getting Started with PrimeVue

Installation

First, you need to install PrimeVue in your Vue.js project:

# Using npm
npm install primevue

# Using yarn
yarn add primevue

You'll also need the PrimeVue styles and icons:

npm install primeicons

Basic Setup

Once installed, you need to configure PrimeVue in your Vue application.

For Vue 3 applications, you can set it up in your main.js file:

import { createApp } from 'vue';
import App from './App.vue';
import PrimeVue from 'primevue/config';
import 'primevue/resources/themes/lara-light-blue/theme.css'; // theme
import 'primevue/resources/primevue.min.css'; // core css
import 'primeicons/primeicons.css'; // icons

const app = createApp(App);
app.use(PrimeVue);
app.mount('#app');

Importing Individual Components

PrimeVue allows you to use components individually. This approach helps to keep your bundle size small by including only the components you need:

<template>
<div>
<h2>My First PrimeVue Component</h2>
<Button label="Click Me" @click="showMessage" />
<Toast />
</div>
</template>

<script>
import Button from 'primevue/button';
import Toast from 'primevue/toast';
import { useToast } from 'primevue/usetoast';

export default {
components: {
Button,
Toast
},
setup() {
const toast = useToast();

const showMessage = () => {
toast.add({
severity: 'success',
summary: 'Success',
detail: 'You clicked the button!',
life: 3000
});
};

return {
showMessage
};
}
}
</script>

Core PrimeVue Components

PrimeVue offers a wide range of components for various UI needs. Let's explore some of the most commonly used ones:

Form Components

InputText

The most basic form component is InputText, which enhances the standard HTML input element:

<template>
<div class="p-field">
<label for="username">Username</label>
<InputText id="username" v-model="username" aria-describedby="username-help" />
<small id="username-help">Enter your username to login.</small>
</div>
</template>

<script>
import InputText from 'primevue/inputtext';

export default {
components: {
InputText
},
data() {
return {
username: ''
};
}
}
</script>

Dropdown provides a way to select an item from a collection:

<template>
<div class="p-field">
<label for="city">City</label>
<Dropdown id="city" v-model="selectedCity" :options="cities" optionLabel="name"
placeholder="Select a City" />
</div>
</template>

<script>
import Dropdown from 'primevue/dropdown';

export default {
components: {
Dropdown
},
data() {
return {
selectedCity: null,
cities: [
{ name: 'New York', code: 'NY' },
{ name: 'London', code: 'LDN' },
{ name: 'Paris', code: 'PRS' },
{ name: 'Tokyo', code: 'TK' }
]
};
}
}
</script>

Data Display Components

DataTable

DataTable is one of the most powerful PrimeVue components. It allows you to display data in a tabular format with features like sorting, filtering, and pagination:

<template>
<DataTable :value="products" :paginator="true" :rows="5"
tableStyle="min-width: 50rem">
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
<Column field="price" header="Price">
<template #body="slotProps">
${{ slotProps.data.price.toFixed(2) }}
</template>
</Column>
</DataTable>
</template>

<script>
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';

export default {
components: {
DataTable,
Column
},
data() {
return {
products: [
{ code: '1001', name: 'Product A', category: 'Electronics', quantity: 10, price: 299.99 },
{ code: '1002', name: 'Product B', category: 'Clothing', quantity: 25, price: 49.99 },
{ code: '1003', name: 'Product C', category: 'Home', quantity: 8, price: 199.99 },
{ code: '1004', name: 'Product D', category: 'Electronics', quantity: 15, price: 399.99 },
{ code: '1005', name: 'Product E', category: 'Clothing', quantity: 30, price: 29.99 },
{ code: '1006', name: 'Product F', category: 'Home', quantity: 12, price: 129.99 },
]
};
}
}
</script>

Card

Card is a flexible container component:

<template>
<Card>
<template #header>
<img alt="user header" src="https://primefaces.org/cdn/primevue/images/usercard.png" />
</template>
<template #title>
Advanced Card
</template>
<template #content>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Inventore sed consequuntur error repudiandae numquam.</p>
</template>
<template #footer>
<Button icon="pi pi-check" label="Save" />
<Button icon="pi pi-times" label="Cancel" class="p-button-secondary" style="margin-left: .5em" />
</template>
</Card>
</template>

<script>
import Card from 'primevue/card';
import Button from 'primevue/button';

export default {
components: {
Card,
Button
}
}
</script>

Overlay Components

Dialog

Dialog is a container that can be positioned anywhere on the page:

<template>
<div>
<Button label="Show Dialog" icon="pi pi-external-link" @click="displayDialog = true" />

<Dialog v-model:visible="displayDialog" header="Dialog Header" :modal="true" :style="{ width: '50vw' }">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<template #footer>
<Button label="Close" icon="pi pi-times" @click="displayDialog = false" class="p-button-text" />
<Button label="Save" icon="pi pi-check" @click="displayDialog = false" autofocus />
</template>
</Dialog>
</div>
</template>

<script>
import Dialog from 'primevue/dialog';
import Button from 'primevue/button';

export default {
components: {
Dialog,
Button
},
data() {
return {
displayDialog: false
};
}
}
</script>

Styling and Theming

PrimeVue comes with several built-in themes that you can easily switch between. The default theme is 'lara-light-blue', but you can choose from various other options:

// In your main.js file
import 'primevue/resources/themes/saga-blue/theme.css'; // saga-blue theme
// or
import 'primevue/resources/themes/vela-green/theme.css'; // vela-green theme
// or
import 'primevue/resources/themes/arya-orange/theme.css'; // arya-orange theme

You can also create custom themes using CSS variables or by customizing the SASS variables provided by PrimeVue.

Practical Example: Building a Contact Manager

Let's create a simple contact manager using PrimeVue components to demonstrate a real-world application.

<template>
<div class="contact-manager">
<Toast />
<Panel header="Contact Manager" class="mb-3">
<div class="p-grid">
<div class="p-col-12 p-md-6">
<h3>Add New Contact</h3>
<div class="p-field">
<label for="name">Name</label>
<InputText id="name" v-model="newContact.name" class="w-full" />
</div>
<div class="p-field">
<label for="email">Email</label>
<InputText id="email" v-model="newContact.email" class="w-full" />
</div>
<div class="p-field">
<label for="phone">Phone</label>
<InputText id="phone" v-model="newContact.phone" class="w-full" />
</div>
<Button label="Add Contact" icon="pi pi-plus" @click="addContact" />
</div>
</div>
</Panel>

<DataTable :value="contacts" :paginator="true" :rows="5"
tableStyle="min-width: 50rem" class="mt-4">
<Column field="name" header="Name"></Column>
<Column field="email" header="Email"></Column>
<Column field="phone" header="Phone"></Column>
<Column header="Actions">
<template #body="slotProps">
<Button icon="pi pi-pencil" class="p-button-rounded p-button-success mr-2"
@click="editContact(slotProps.data)" />
<Button icon="pi pi-trash" class="p-button-rounded p-button-danger"
@click="confirmDelete(slotProps.data)" />
</template>
</Column>
</DataTable>

<Dialog v-model:visible="displayEditDialog" header="Edit Contact" :modal="true"
:style="{ width: '30vw' }">
<div class="p-field">
<label for="edit-name">Name</label>
<InputText id="edit-name" v-model="editingContact.name" class="w-full" />
</div>
<div class="p-field">
<label for="edit-email">Email</label>
<InputText id="edit-email" v-model="editingContact.email" class="w-full" />
</div>
<div class="p-field">
<label for="edit-phone">Phone</label>
<InputText id="edit-phone" v-model="editingContact.phone" class="w-full" />
</div>
<template #footer>
<Button label="Cancel" icon="pi pi-times" @click="displayEditDialog = false" class="p-button-text" />
<Button label="Save" icon="pi pi-check" @click="saveEditedContact" />
</template>
</Dialog>

<ConfirmDialog></ConfirmDialog>
</div>
</template>

<script>
import { ref } from 'vue';
import Panel from 'primevue/panel';
import InputText from 'primevue/inputtext';
import Button from 'primevue/button';
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';
import Dialog from 'primevue/dialog';
import Toast from 'primevue/toast';
import ConfirmDialog from 'primevue/confirmdialog';
import { useToast } from 'primevue/usetoast';
import { useConfirm } from 'primevue/useconfirm';

export default {
components: {
Panel,
InputText,
Button,
DataTable,
Column,
Dialog,
Toast,
ConfirmDialog
},
setup() {
const toast = useToast();
const confirm = useConfirm();

const contacts = ref([
{ id: 1, name: 'John Doe', email: '[email protected]', phone: '555-1234' },
{ id: 2, name: 'Jane Smith', email: '[email protected]', phone: '555-5678' },
{ id: 3, name: 'Bob Johnson', email: '[email protected]', phone: '555-9012' }
]);

const newContact = ref({ name: '', email: '', phone: '' });
const editingContact = ref({});
const displayEditDialog = ref(false);

const addContact = () => {
if (!newContact.value.name || !newContact.value.email || !newContact.value.phone) {
toast.add({ severity: 'error', summary: 'Error', detail: 'Please fill in all fields', life: 3000 });
return;
}

const id = contacts.value.length ? Math.max(...contacts.value.map(c => c.id)) + 1 : 1;
contacts.value.push({
id,
name: newContact.value.name,
email: newContact.value.email,
phone: newContact.value.phone
});

newContact.value = { name: '', email: '', phone: '' };
toast.add({ severity: 'success', summary: 'Success', detail: 'Contact added', life: 3000 });
};

const editContact = (contact) => {
editingContact.value = { ...contact };
displayEditDialog.value = true;
};

const saveEditedContact = () => {
const index = contacts.value.findIndex(c => c.id === editingContact.value.id);
if (index !== -1) {
contacts.value[index] = editingContact.value;
toast.add({ severity: 'success', summary: 'Success', detail: 'Contact updated', life: 3000 });
displayEditDialog.value = false;
}
};

const confirmDelete = (contact) => {
confirm.require({
message: `Are you sure you want to delete ${contact.name}?`,
header: 'Confirmation',
icon: 'pi pi-exclamation-triangle',
acceptClass: 'p-button-danger',
accept: () => {
contacts.value = contacts.value.filter(c => c.id !== contact.id);
toast.add({ severity: 'success', summary: 'Success', detail: 'Contact deleted', life: 3000 });
}
});
};

return {
contacts,
newContact,
editingContact,
displayEditDialog,
addContact,
editContact,
saveEditedContact,
confirmDelete
};
}
}
</script>

<style scoped>
.contact-manager {
padding: 20px;
}
.p-field {
margin-bottom: 1.5rem;
}
</style>

This example demonstrates a complete mini-application that uses multiple PrimeVue components, including:

  • DataTable for displaying contacts
  • Dialog for editing contacts
  • ConfirmDialog for confirming deletions
  • Toast for notifications
  • InputText for form fields
  • Button for actions
  • Panel for layout organization

Advanced Features

Form Validation with PrimeVue

PrimeVue works well with form validation libraries. Here's a simple example using Vue's built-in validation:

<template>
<div class="form-demo">
<div class="p-field">
<label for="email">Email</label>
<InputText id="email" type="text" v-model="email" :class="{'p-invalid': emailError}" />
<small class="p-error" v-if="emailError">{{ emailError }}</small>
</div>
<Button label="Submit" @click="validateForm" />
</div>
</template>

<script>
import InputText from 'primevue/inputtext';
import Button from 'primevue/button';

export default {
components: {
InputText,
Button
},
data() {
return {
email: '',
emailError: ''
};
},
methods: {
validateForm() {
this.emailError = '';

if (!this.email) {
this.emailError = 'Email is required';
return;
}

const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(this.email)) {
this.emailError = 'Please enter a valid email address';
return;
}

alert('Form is valid!');
}
}
}
</script>

Dynamic Component Loading

For large applications, you might want to load PrimeVue components dynamically to improve performance:

<template>
<div>
<Button label="Show Complex Component" @click="loadComplexComponent" />
<div v-if="showComponent">
<component :is="dynamicComponent"></component>
</div>
</div>
</template>

<script>
import { defineAsyncComponent } from 'vue';
import Button from 'primevue/button';

export default {
components: {
Button
},
data() {
return {
showComponent: false,
dynamicComponent: null
};
},
methods: {
loadComplexComponent() {
this.dynamicComponent = defineAsyncComponent(() =>
import('./ComplexDataTable.vue')
);
this.showComponent = true;
}
}
}
</script>

Summary

PrimeVue is a powerful UI component library for Vue.js that offers a comprehensive set of components for building modern web applications. In this guide, we've covered:

  1. Basic setup and installation of PrimeVue
  2. Core components and their usage patterns
  3. Styling and theming options
  4. A practical contact manager application
  5. Advanced features like form validation and dynamic component loading

With PrimeVue, you can rapidly build professional-looking applications while focusing on the business logic rather than reinventing UI components. The library is actively maintained, well-documented, and has a strong community, making it an excellent choice for Vue developers at all levels.

Additional Resources

Practice Exercises

  1. Create a simple to-do list application using PrimeVue components (InputText, Button, DataTable, Checkbox).
  2. Build a dynamic form with validation that uses multiple input types (text, dropdown, calendar, etc.).
  3. Create a dashboard layout using PrimeVue's layout components (Card, Panel, TabView).
  4. Build a shopping cart that includes a DataTable for products, InputNumber for quantities, and a summary panel.
  5. Create a user registration form with multi-step wizard navigation using PrimeVue's Steps component.

By practicing with these exercises, you'll gain valuable experience with PrimeVue and improve your Vue.js skills.

💡 Found a typo or mistake? Click "Edit this page" to suggest a correction. Your feedback is greatly appreciated!