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:

bash
# Using npm
npm install primevue

# Using yarn
yarn add primevue

You'll also need the PrimeVue styles and icons:

bash
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:

javascript
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:

html
<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:

html
<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:

html
<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:

html
<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:

html
<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:

html
<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:

javascript
// 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.

html
<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:

html
<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:

html
<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.



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