ben.IT
ben.IT

Reputation: 1610

How to open and close conditionally a tag in vue.js?

I want to render 3 videos in a bootstrap row with vue.js.

I need to open <div class="row"> and close this tag each 3 videos in order to wrap the wrap them inside.

I don't know how to do that with vueJS?

HTML markup:

 <div class="container" id="video-list">
        <div v-for="(item, index) in items"><!--how to open this tag only if index%3==0?-->
            <div class="row">
                <div class="col-md-4 col-sm-4 ">
                    <h3>{{item}} {{index}}</h3>
                    <video class="video-js vjs-default-skin vjs-16-9 vjs-big-play-centered" controls
                           preload="auto" width="640" height="264" poster="video-poster.png"
                           data-setup="{}">
                        <source :src="'video/' + item" type='video/mp4'>
                    </video>
                </div>
            </div> <!--how to close this tag only if index%3==0?-->
        </div>
    </div>

Javascript code:

        var videos = new Vue({
            el: '#video-list',
            data: {
                items: JSON.parse(result)
            }
        });

I saw Conditional Rendering instructions but when I apply this to this div class="row" this hide the child tags that contain videos!

In my case, I don't want to manage tag rendering, I need to be able to open/close conditionally a tag element.

Upvotes: 1

Views: 1798

Answers (3)

Mohd_PH
Mohd_PH

Reputation: 1677

So here is an answer to a question to divide an array into chunks, I used it to achieve the behavior you need, and here is the example:

// https://stackoverflow.com/a/10456644/4738332
Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
    return Array.from(Array(Math.ceil(this.length/n)), (_,i)=>this.slice(i*n,i*n+n));
}});

Vue.component('app-row', {
	props:['items'],
  template:`
  	<div class="row">
    	
      <div class="item" v-for="item in items">{{item}}</div>
    
    </div>
  `

})

new Vue({
	el:"#app",
  data:{
  	items: [1,2,3,4,5,6,7,8,9,10]
  },
  computed:{
  	getRowsItems(){      
      return this.items.chunk(3)
    }
  }
  
})
.row{
  background-color: green;
  margin: 20px;
  padding: 10px;
}

.item{
  background-color: blue;
  margin: 4px;
  color: white;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>

<div id="app">
  <app-row v-for="rowItems in getRowsItems" :items="rowItems"></app-row>
</div>

Upvotes: 0

Gabriel Umbelino
Gabriel Umbelino

Reputation: 86

You can process the items to a matrix and iterate into it.

var videos = new Vue({
  el: '#video-list',
  data: function() {

    var items = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];

    var rows = [];

    while (items.length > 0) {
      rows.push(items.splice(0, 3));
    }

    return {
      rows: rows
    };
  }
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div class="container" id="video-list">
  <div v-for="(row, i) in rows" class="row">
    <div v-for="(col, j) in row" class="col-md-4 col-sm-4">
      <h3>{{ col + "(" + j + " " + i + ")"}}</h3>
    </div>
  </div>
</div>

Upvotes: 6

V. Sambor
V. Sambor

Reputation: 13389

Unfortunately you can't do like that. You'll need to make something like this:

<div class="container" id="video-list">
  <div v-for="(item, index) in items">

    <!--how to open this tag only if index%3==0?-->
    <div class="row" v-if="index % 3 === 0">
      <div class="col-md-4 col-sm-4 ">
        <h3>{{item}} {{index}}</h3>
        <video class="video-js vjs-default-skin vjs-16-9 vjs-big-play-centered" controls preload="auto" width="640" height="264" poster="video-poster.png" data-setup="{}">
          <source :src="'video/' + item" type='video/mp4'>
        </video>
      </div>
    </div>
    <!--how to close this tag only if index%3==0?-->

      <!-- Notice, here you don't have the row anymore -->
      <div class="col-md-4 col-sm-4 " v-else>
        <h3>{{item}} {{index}}</h3>
        <video class="video-js vjs-default-skin vjs-16-9 vjs-big-play-centered" controls preload="auto" width="640" height="264" poster="video-poster.png" data-setup="{}">
          <source :src="'video/' + item" type='video/mp4'>
        </video>
      </div> 
  </div>
</div>

Maybe you will create a small component to not duplicate the code inside the row.

Upvotes: 0

Related Questions