DEV Community

Doan Trong Nam
Doan Trong Nam

Posted on

2 1 1 1 1

Wrapping PrimeVue Components: Tips for a Better Developer Experience

PrimeVue is a fantastic UI library for Vue.js developers, offering a rich set of components that are both customizable and easy to integrate. However, as your application grows, you might find yourself repeating the same configurations—like base styles, default props, or custom logic—across multiple instances of PrimeVue components. This is where wrapping PrimeVue components into your own custom components becomes a game-changer. In this blog post, I’ll walk you through why wrapping is beneficial, a common issue you might face with VSCode’s prop autocompletion, and how to fix it for a smoother development experience.

Why Wrap PrimeVue Components?

When you use PrimeVue components directly in your templates, they work great out of the box. But in a real-world application, you often need more control and consistency. Here are a few reasons why wrapping PrimeVue components into your own custom components makes sense:

  1. Centralized Base Styles PrimeVue components come with their own default styles, but your app might require a consistent look and feel that aligns with your design system. By wrapping a component (e.g., p-button from PrimeVue), you can apply custom classes or styles globally without repeating them in every template.
<!-- Before wrapping -->
<p-button label="Click Me" class="my-custom-button" />

<!-- After wrapping -->
<app-button label="Click Me" />
Enter fullscreen mode Exit fullscreen mode
<!-- ~/components/app/button.vue -->
<template>
  <p-button class="my-custom-button" />
</template>
Enter fullscreen mode Exit fullscreen mode
  1. Default Props for Consistency If your app uses a PrimeVue component with certain props repeatedly (e.g., size="small" or severity="success" for a p-button), you can set these as defaults in your wrapped component. This reduces boilerplate code and ensures consistency.
<!-- ~/components/app/button.vue with default props -->
<template>
  <p-button rounded size="large" />
</template>
Enter fullscreen mode Exit fullscreen mode
  1. Custom Logic or Behavior Wrapping allows you to add custom logic—like event handlers, computed properties, or validation—specific to your app’s needs, all while keeping the original PrimeVue component intact.

By wrapping PrimeVue components, you create reusable building blocks tailored to your project, making your codebase cleaner and more maintainable.

The Problem: VSCode Stops Suggesting Props

While wrapping is great, it introduces a small hiccup: VSCode’s autocompletion for props might stop working. When you use a PrimeVue component directly (e.g., <p-button>), tools like Vue - Official Extension (Vue’s language support extension for VSCode) recognize it and suggest all available props (label, icon, loading, etc.). But once you wrap it in <app-button>, VSCode no longer knows what props the underlying Button component accepts because app-button is just a custom component to the editor.

For example:
Editor not suggest label prop

Typing label here won’t trigger prop suggestions, and you might need to manually refer to PrimeVue’s documentation. This slows down development and can be frustrating, especially for larger teams or complex components.

The Solution: Add Prop Definitions
To restore VSCode’s prop autocompletion, you need to tell Vue - Official Extension what props your wrapped component accepts. This can be done by defining the props in your custom component and leveraging TypeScript or Vue’s defineComponent for better tooling support. Here’s how:

Step 1: Define Props in Your Wrapped Component
Update app/button.vue to explicitly declare the props it accepts, matching the props of the underlying PrimeVue Button component.

<!-- ~/components/app/button.vue -->
<template>
  <p-button v-bind="props" />
</template>

<script lang="ts" setup>
import type { ButtonProps } from 'primevue'

interface AppButtonProps extends /* @vue-ignore */ ButtonProps {}

const props = defineProps<AppButtonProps>()
</script>
Enter fullscreen mode Exit fullscreen mode

Step 2: Add slot if needed

<!-- ~/components/app/button.vue -->
<template>
  <p-button v-bind="props">
    <template #icon v-if="$slots.icon">
      <slot name="icon" />
    </template>
    <slot />
  </p-button>
</template>

<script lang="ts" setup>
import type { ButtonProps } from 'primevue'

interface AppButtonProps extends /* @vue-ignore */ ButtonProps {}

const props = defineProps<AppButtonProps>()
</script>
Enter fullscreen mode Exit fullscreen mode

Step 3: Add default prop if needed by withDefaults()

<!-- ~/components/app/button.vue -->
<template>
  <p-button v-bind="props">
    <template #icon v-if="$slots.icon">
      <slot name="icon" />
    </template>
    <slot />
  </p-button>
</template>

<script lang="ts" setup>
import type { ButtonProps } from 'primevue'

interface AppButtonProps extends /* @vue-ignore */ ButtonProps {
  rounded?: boolean
}

const props = withDefaults(defineProps<AppButtonProps>(), {
  rounded: true
})
</script>
Enter fullscreen mode Exit fullscreen mode

Step 4: Verify Autocompletion
With Vue - Official Extension installed in VSCode (ensure you have the Vue Official extension), try using in a template:

<app-button label="Click Me" />
Enter fullscreen mode Exit fullscreen mode

Now, when you type <app-button , VSCode will suggest label, icon, loading, ... just like it would for the original <p-button> component.

Image description

Wrapping Up

Wrapping PrimeVue components is a powerful technique to enforce consistency, reduce repetition, and tailor components to your app’s needs. While it might break VSCode’s prop autocompletion initially, defining props explicitly (with or without TypeScript) brings it back and keeps your workflow smooth. Next time you’re building with PrimeVue, give wrapping a try—it’s a small investment that pays off in the long run!

What’s your favorite PrimeVue component to customize? Let me know in the comments!

This blog post is concise, practical, and follows your requested structure. You can tweak the examples or tone to match your style before posting it on Dev.to. Let me know if you’d like any adjustments!

Example source code: https://github.com/1337NamNori/primevue-wrap-tutorial

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay