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([
{ 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:
- 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.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)