Use vue.js to add a block of content after every sixth iteration in a loop

Currently, I have a list of offer cards rendering through a loop. I am adding a row div every 3rd column (bootstrap) element. Now, I need to also add another column element (banner block) for every 6th element in order to achieve a layout like the one shown in the following image:

https://i.stack.imgur.com/ugMet.gif

How can I go about implementing this?

Here is my current code:

<div class="row" v-for="i in Math.ceil(offers.length / 3)">
    <div class="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12" v-for="offer in offers.slice((i-1)*3, i*3)">
        <h2>{{offer.name}}</h2>
        <h2>{{offer.desc}}</h2>
    </div>
</div>

Answer №1

Using a for loop:

    <div class="mycol" v-for="(offer,ind) in offers">
      <template v-if="ind % 5 == 0">
       <h2>banner</banner>
      </template>
      <template v-else>
       <h2>{{offer.name}}</h2>
       <h2>{{offer.desc}}</h2>
      </template>
    </div>

To create a new line for every third column, you can use the following CSS:

.mycol:nth-child(3n+1){
 clear:left;
}

Answer №2

In my opinion, it would be beneficial to shift the focus of your programming from the view to the view model. Consider creating a computed property that organizes your data into groups of offers and banners, as well as rows, and then utilize this computed property in a simple manner.

const chunk = (arr, size) =>
  arr
  .reduce((acc, _, i) =>
    (i % size) ?
    acc :
    [...acc, arr.slice(i, i + size)], []);

new Vue({
  el: '#app',
  data: {
    offers: []
  },
  computed: {
    rows() {
      const withBanners = chunk(this.offers, 5).map((arr) => [...arr, {name: 'banner', type: 'Banner'}]).reduce((a, b) => a.concat(b), []);

      return chunk(withBanners, 3);
    }
  },
  mounted() {
    setTimeout(() => {
      this.offers = [{
          name: 'offer'
        },
        {
          name: 'offer'
        },
        {
          name: 'offer'
        },
        {
          name: 'offer'
        },
        {
          name: 'offer'
        },
        {
          name: 'offer'
        },
        {
          name: 'offer'
        },
        {
          name: 'offer'
        },
        {
          name: 'offer'
        },
        {
          name: 'offer'
        },
        {
          name: 'offer'
        }
      ];
    }, 500);
  }
});
#app {
  display: grid;
}

.row {
  display: grid;
  grid-gap: 2rem;
  grid-template-columns: repeat(3, auto);
  justify-content: left;
}

.box {
  width: 8rem;
  height: 8rem;
}

.banner {
  background-color: #f9c;
}

offer {
  background-color: #99f;
}
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <div class="row" v-for="row in rows">
    <div class="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12" v-for="item in row">
      <div v-if="item.type === 'Banner'" class="banner box">
        <h2>{{item.name}}</h2>
      </div>
      <div v-else class="offer box">
        <h2>{{item.name}}</h2>
      </div>
    </div>
  </div>
</div>

Answer №3

This solution will cater to your exact needs. I had to tweak the data a bit because Vue's templating language is not tailored for handling logic in this particular scenario

HTML

<div id="app">
  <div v-for="items in rows" class="row>
    <div v-for="item in items" class="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12">{{item}}</div>
  </div>
</div>

SCRIPT

created () {
    while (this.items.length > 0) {
      const howMany = (this.rows.length % 3 === 0) ? 3 : 2
      const row = this.items.splice(0, howMany)
      if (howMany === 2) row.push('banner')
      this.rows.push(row)

    }
},

https://jsfiddle.net/jamesharrington/k6c0rgL3/17/

Answer №4

If you're looking to insert a banner every sixth element but display the sixth itself, it might be more efficient to manipulate your data object directly by adding the banner into it. You can achieve this by splitting your array in the following way:

let firstPart = myData.slice(0,5)
let lastPart = myData.slice(5,)

let newData = [...firstPart, banner, ...lastPart]

After implementing this solution, you'll only need to repeat the process every 6 elements.

Answer №5

Using flex is highly recommended if feasible. To implement this, refer to the following code snippet: http://jsfiddle.net/p6yq5mxv/

const app = new Vue({
  el: '#app',
  data() {
    return {
        items: _.times(20, i => ({type: 'offer'})),
    };
  },
  computed: {
    itemsWithBanners() {
      let result = [];
      this.items.forEach((item, idx) => {
        if (idx && idx % 5 === 0) {
            result.push({type: 'banner'});
        }
        result.push(item);
      });
      return result;
    },
  },
});

Answer №6

Appreciate all the help, I implemented Roy J's solution with some modifications for my specific scenario and achieved the desired outcome. Here is my updated code:

<template>
  <div class="section-space80 results-col" >
    <div class="container" >
      <div class="row">
          <div class="col-md-12">
            <div class="wrapper-content bg-white pinside40">
              <div class="row" v-for="row in rows">
                <div v-for="offer in row" class="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12">
                  <div class="lender-listing" v-if="offer.type && offer.type === 'Banner'">
                    <div class="lender-head">
                        Banner
                    </div>
                  </div>
                  <div class="lender-listing" v-if="offer.mfoName">
                    <div class="lender-head">
                        <div class="lender-logo">Offer</div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
      </div>
    </div>
  </div>
</template>

<script>
  const chunk = (arr, size) =>
  arr
  .reduce((acc, _, i) =>
    (i % size) ?
    acc :
    [...acc, arr.slice(i, i + size)], []);

  import axios from 'axios'
  export default {
    data() {
      return {
        showOffers: true,
        loanOffers: [],
        isVisible: false,
        loadMore: true,
        offset: 0,
        rows: ''

      }
    },

    methods: {
      getOffersList: function () {
        let dataElements = this
        dataElements.loading = true
        axios.get('/api/v1/getUserOffers')
          .then(function (response) {
            dataElements.loanOffers = response.data
            const withBanners = chunk(dataElements.loanOffers, 5).map((arr) => [...arr, {name: 'banner', type: 'Banner'}]).reduce((a, b) => a.concat(b));
            dataElements.rows = chunk(withBanners, 3);
          })
      },
    },
    beforeMount(){
      this.getOffersList()
    }
  }

</script>

Answer №7

A suggestion I have is to utilize a template and iterate through it in a loop. Within the loop, you can check for a condition using v-if="i%6" --> displaying your article, otherwise display your ad with v-else.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The Sentinel of Vue-router Navigation

I am trying to create a router guard, but I am having trouble with the logic. The setAuthentication part works fine when it's equal to true, but the else part is giving me issues. I need the KrediForm page to only be accessible when setAuthentication ...

What is the purpose of storing the Vue instance in a variable or constant?

As a newcomer to Vue, I've noticed that in many tutorials and documentation sources, the new Vue instance is often stored in a variable like app. I'm curious, what is the benefit of saving the Vue instance in a constant or variable? const app = ...

What is the best way to interact with my component in React?

As a newcomer to Reactjs, I have a question regarding my current setup: The components in my project include navComponent.js, stackComponent.js, and nav.js I am trying to pass data from stackComponent.js to navComponent.js so that the nav.js data can be ...

Theme.breakpoints.down not being acknowledged by MUI breakpoints

The Challenge: Implement a hamburger menu to replace the navMenu on tablet and smaller screens After successfully compiling in VS code terminal, encountering an error in the browser: Error Message: TypeError: Cannot read properties of undefined (reading ...

Tallying the number of words delimited by a comma

Here is how my counter function is structured: function count() { var value = ids.val(); return (value == '') ? 0 : value.replace(/\s,?|,$/g, '').split(',').length; } After checking the returned value, data is ...

Issues persist with jQuery ajax request attempting to retrieve data from database

I attempted to retrieve data from my database using jQuery AJAX. Below is the code snippet I used: <script> $(document).ready(function(){ function fetch_data(){ $.ajax({ type:"POST", url:"http://localhost:88/phpPoint/select.php", success:function(re ...

Issue with Custom Tooltip in Mootools 1.2 - Images displaying prematurely before hover action

Encountering an issue with Mootools 1.2 Tips (custom tooltips) We are currently utilizing Joomla with the latest update that includes Mootools 1.2, and I am working with the following JS code: $$('.tipz').each(function(element,index) { ...

Enhancing Typography in Material UI with Custom Breakpoints in React CustomThemes

Currently, I am utilizing material UI and React to develop a single-page application (SPA). However, I have encountered an issue with ensuring that my pages are responsive for smaller screen sizes. To address this, I have been manually adding fontSize: { x ...

Tips for excluding specific codes from running in BeforeAll for a specific Describe() block in Jasmine

Currently, I am in the process of writing a Jasmine unit test spec. The JS file contains several describe() blocks. Within the BeforeAll function, my objective is to execute a function only for the "A" and "C" Describe-Blocks. How can this be accomplished ...

Tailored design - Personalize interlocking elements

I am currently working on a custom theme and I am trying to adjust the font size of Menu items. In order to achieve this, I have identified the following elements in the tree: ul (MuiMenu-list) MuiListItem-root MuiListItemText-root If I want to modify th ...

partial download between servers

I have been attempting to transfer/copy a large file from a remote server to my server in segmented parts or chunks. My initial approach involved utilizing a script I found here: . After making some modifications, I integrated a form into the script and e ...

Utilize dynamically generated form fields to upload multiple files at once

Currently, as I delve into learning the MEAN stack, I am encountering difficulties with file uploads. Specifically, within a company form: this.companyForm = this.fb.group({ trucks: this.fb.array([]), ... }); The 'trucks' field i ...

Enhanced Rating System for Asp.Net

How can I retrieve the selected value (CurrentValue) of the ASP.NET Rating control in javascript? I have it implemented within a datagrid, and I am facing difficulty in accessing the CurrentValue property. Any suggestions or solutions for this issue woul ...

Why does the onBlur event function in Chrome but fails to work in Safari?

I've encountered a problem with the onBlur event in react-typescript. To replicate the issue, I clicked the upButton repeatedly to increase the number of nights to 9 or more, which is the maximum allowed. Upon further clicking the upButton, an error m ...

Retrieve a zip file using React and Node from a RESTful API

I have an application built with React and Node where I have a table that includes a download button. Clicking the download button triggers a request to my Node app, which in turn should call a REST API to download a zip file directly into the browser. In ...

Uploading photos to Postgres through express/multer

Currently, I am using Postman to send images to a POST route through the Express library. However, when I retrieve the buffer of binary data, I am unable to process it accordingly. Will using body-parser resolve this issue? This is how I am uploading the ...

show button after the page has finished loading

I have a button similar to this: <input type="submit" id="product_197_submit_button" class="wpsc_buy_button" name="Buy" value="Add To Cart"> However, I am encountering an issue where if the user clicks the button before all scripts are loaded, an e ...

Display the chosen alternative in a Bootstrap dropdown menu

I am currently facing an issue with the dropdown list in my bootstrap menu. <li class="dropdown"> <a aria-expanded="false" aria-haspopup="true" role="button" data-toggle="dropdown" class="dropdown-toggle" href="#">Chose option<span class="c ...

Using the `preventDefault` method within an `onclick` function nested inside another `onclick

I am currently working on an example in react.js <Card onClick="(e)=>{e.preventDefault(); goPage()}"> <Card.body> <Media> <img width={64} height={64} className="mr-3" ...

I am experiencing an issue where the jquery sleep function is not being executed during

I currently have an Ajax request that is awaiting a response from another process. function checkProcess() { var flag = 0; while (flag === 0) { $.ajax({ url: "cs/CheckForProcess", async: false, success: ...