Skip to content
Advertisement

Vue: convention for conditional props in dynamic components?

I am fairly new to Vue, so if what I am doing is absurd, please let me know.

A common convention in many of my components is something like this (only showing relevant parts of code):

thing = {text:"some text", href: "https://a.link"}

<template>
  <div>
    <a v-if="thing.href" :href="thing.href">{{thing.text}}</a>
    <span v-else>{{thing.text}}</span>
  </div>
</template>

I dislike this as thing.text may in actuality be a lot of stuff (not just text).

Further, I dislike the redundancy for rendering the anchor tag i.e. if there is an href be an anchor tag with an href.

Thus I would like to shorten and clean this up like so:

<template>
  <div>
    <div :is="complexThing.href ? 'a' : 'span'" :href="complexThing.href">{{complexThing.lotsOfStuff}}</div>
  </div>
</template>

Which is nice, we are down to one line, but at the cost of href being bound to nothing when it doesn’t exist…

So is there a way to conditionally bind a prop?

Of course I could wrap this convention into a component of its own. However, I find that what it is, is very dependent on the component I am using it in. I do not like having to copy and paste a chunk of identical code between an if-else statement just to get an href.

Thoughts? Ideas?

e.g.

<template>
  <div :is="href ? 'a' : or" :href="href">
  <!-- href=(unknown) will show in inspector if href is undefined -->
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'AnchorOr',
  props: ['or', 'href']
}
</script>

<style>

</style>

which can then be used like:

<AnchorOr class="inline-text" :or="span">{{text}}</AnchorOr>
<AnchorOr class="linked-module" :or="div">{{component}}</AnchorOr>

Answer

In your small example, I would leave it as-is; however if {{ thing.text }} were instead a larger template partial then duplicating it is a no-no.

You would normally use <component> for situations like this:

<component v-bind="thingProps">{{ thing.text }}</component>
computed: {
  thingProps() {
    return this.thing.href
      ? { is: 'a', href: this.thing.href }
      : { is: 'span' };
  }
}
Advertisement