Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrap element using v-if, otherwise just have content itself

Tags:

vue.js

I have a set of elements being generated in a v-for directive that, if the object has a url property, get wrapped in an <a> tag - otherwise, I need it to just emit the element itself.

For example,

var data = {
    events: [
        {name: "Foo"},
        {name: "Bar", url: "google.com"}
    ]
};

and the corresponding HTML:

<div v-for="event in events">
    <span>{{event.name}}</span>
</div>

What I need is to wrap the <span> in an <a v-bind:href="url"> only if there is a url property present.

I understand I could use a v-if and use two spans, such as:

<span v-if="!event.url">{{event.name}}</span>
<a v-bind:href="event.url" v-if="event.url">
    <span>{{event.name}}</span>
</a>

However, in my use case the <span> element here could be massive and I don't want to repeat myself just to wrap the element.

Is there a way to achieve a conditional wrap such as the above?

like image 666
Qix - MONICA WAS MISTREATED Avatar asked May 08 '17 06:05

Qix - MONICA WAS MISTREATED


People also ask

How to use v-if in vue js?

The v-if directive is a Vue. js directive used to toggle the display CSS property of a element with a condition. If the condition is true it will make it visible else it will make it invisible. First, we will create a div element with id as app and let's apply the v-if directive to this element with data.

How do I know if my Vue slot has content?

To only show slot if it has content with Vue. js, we can check the this. $slots property in our component. to check if the footer slot is added with !!

How does v-if work?

v-if. The directive v-if is used to conditionally render a block. The block will only be rendered if the directive's expression returns a truthy value.

Can we use V-if and V-show together?

If v-if == true and v-show changes from true to false , the leave transition occurs as expected. If v-show== true and v-if changes from true to false , the element is immediately removed, no transition occurs. My use case for this is using both v-if and v-show around media ( img , video ).


1 Answers

You can use v-html for example and render your logic inside a function:

function wrapSpan(el, link) { // link wrapper function
  return `<a href="${link}">${el}</a>`;
}

new Vue({
  el: '#app',
  data: {
    events: [
      {name: "Foo"},
      {name: "Bar", url: "google.com"}
    ]
  },
  methods: {
    element: function(i) {
      const name = this.events[i].name;
      const url = this.events[i].url || null;
      const span = `<span style="color: green">${name}</span>`; // long span
      return (url) ? wrapSpan(span, url) : span;
    }
  }
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
  <div v-for="(event, index) in events">
    <span v-html="element(index)"></span>
  </div>
</div>
like image 161
Egor Stambakio Avatar answered Sep 19 '22 00:09

Egor Stambakio