klodoma
klodoma

Reputation: 4599

VUEJS Wrap Element in a link

I would like to wrap an element with a link ONLY if a link is available:

Normally I would use:

    <a v-if="url" href="url">
      <some-content></some-content>
    </a>
    <some-content v-else></some-content>

BUT this leads to a lot of code duplication, especially if some-content is complex.

I tried to use it like this:

    <wrap-link :url="url">
      <some-content></some-content>
    </wrap-link>

Where wrap-link is like the following, but I can't get rid of the "span" in the v-else part.

    <template>
      <a v-if="url" :href="url">
        <slot></slot>
      </a>
      <span v-else>
        <slot></slot>
      </span>
    </template>

    <script>
    export default {
      props: {
        url: { type: String, default: '' },
      }
    }
    </script>

Any suggestions?

Upvotes: 1

Views: 431

Answers (1)

tony19
tony19

Reputation: 138336

Vue 3

Vue 3 allows multiple root nodes, so putting the v-else directive directly on the <slot> in the root is allowed:

<template>
  <a v-if="url" :href="url">
    <slot></slot>
  </a>
  <slot v-else></slot>
</template>

demo 1

Vue 2 or Vue 3

In either version of Vue, you could use a <component> whose properties are computed based on url:

<template>
  <component :is="component" v-bind="props">
    <slot></slot>
  </component>
</template>

<script>
export default {
  props: {
    url: { type: String, default: '' }
  },
  computed: {
    component() {
      return this.url ? 'a' : 'slot'
    },
    props() {
      return this.url ? { href: this.url } : null
    }
  }
}
</script>

demo 2

Upvotes: 3

Related Questions