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
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([
]);
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:
- Basic setup and installation of PrimeVue
- Core components and their usage patterns
- Styling and theming options
- A practical contact manager application
- 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
- PrimeVue Official Documentation
- PrimeVue GitHub Repository
- PrimeFlex - Flexbox CSS Utility Library (works well with PrimeVue)
Practice Exercises
- Create a simple to-do list application using PrimeVue components (InputText, Button, DataTable, Checkbox).
- Build a dynamic form with validation that uses multiple input types (text, dropdown, calendar, etc.).
- Create a dashboard layout using PrimeVue's layout components (Card, Panel, TabView).
- Build a shopping cart that includes a DataTable for products, InputNumber for quantities, and a summary panel.
- 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!