DEV Community

Alexander Nenashev
Alexander Nenashev

Posted on • Updated on

Conditional wrap component in Vue 3

Often it's needed to wrap some part of a template in a wrapper <div> for example. It seems easy using v-if but we have a duplication we'd like to avoid:

<div v-if="isWrapped" class="wrapper">
  <!-- some big chunk of markup -->
</div>
<template v-else>
  <!-- the same big chunk -->
</template>
Enter fullscreen mode Exit fullscreen mode

Let's explore our options how we can solve this task without the duplication. Let's call our component <wrap> and our component that wraps the content a wrapper. Our wrap component is stateless so let's make it functional.

Our first option would be simple. We support a wrapper component and its props:

See on Vue SFC Playground

import { h } from 'vue';
export default function Wrap({wrapper}, {slots, attrs}){
  return wrapper ? h(wrapper, attrs, slots.default()) : slots.default();
}

Wrap.props = ['wrapper'];
Enter fullscreen mode Exit fullscreen mode

Usage:

  <wrap :wrapper="isWrapped && 'div'" class="wrapper">
    <p>
      I'm wrapped
    </p>
  </wrap>
Enter fullscreen mode Exit fullscreen mode

The result is pretty sufficient, you can use any wrapper component with a default slot. But a problem here is that for more complex cases like having multiple nested wrappers we should define the wrapper outside our markup since having a functional wrapper component inside :wrapper property looks pretty messy. In the next posts of this series we'll explore other options of defining our conditional wrap component.

Top comments (0)