0

I am new in stack overflow.
I am using Vue3 + tailwindcss.

I want to create dyamic grid like this

Corrrection: Here i want repetitive layout and the item of loop are dynamic

Here is My code:

<template>
  <div class="min-h-screen flex items-center bg-purple-500">
  <div class="flex-1 max-w-4xl mx-auto p-8">
    <ul class="grid grid-cols-12 gap-8">
      <template v-for="(i,index) in 8" :key="index">
       <li

          class="col-span-12 sm:col-span-6 md:col-span-4  bg-white rounded-lg shadow-xl"
           v-if="updateCounter(index) || (index+1) % 8 != 0"
        >
          <div class="h-24"> {{ index }} {{updateCounter(index) }}</div>
       </li>
        <li
         v-else
          class="col-span-12 sm:col-span-6 md:col-span-6 bg-white rounded-lg shadow-xl"
         >
          <div class="h-24">{{ index }}  </div>
       </li>
      </template>

    </ul>
  </div>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const count = ref<number>(2)
const checkForCols = ref<boolean>(false);
const total = ref<number>(6)

const updateCounter = (index: any) => {
  if( total.value == index ){ // 0 = (0  1) , 1 = (1  1)+1, 2 = (2  1)+1, 3 = (3  1)+1,4 = (4  1) + 1, 5 = (5  1)+1
    total.value = total.value + 6 + count.value
    return true
  } else {
    return false
  }
}
</script>

But i get Wrong output.

I already spend 2 day but i can't find any solution.
So can anyone help me to how i do this?

Thank you in advance.

1 Answer 1

3

What really complicates your solution is you're modifying the state while calculating the layout (in the v-for loop). Never do that!

When you change the value of state, everything that uses that piece of reactive state gets recalculated (including the items that have already been looped through).
It's an anti-pattern, for a couple of reasons:

  • it often leads to performance issues (changes triggering each other endlessly)
  • it's particularly difficult to follow the mutations trail, while trying to debug it and everyone, including yourself, will have a hard time debugging it, should it start failing.

The fact you asked the question is proof to it. I'm confident you'd have figured out the function below by yourself, had you not modified the state inside the loop.


What you need is:

  • the count
  • a function returning md:col-span-${x} correctly for the last items based on count and index, along these lines:
const count = ref(8)
const getMdClass = (index) => {
  const rest = count.value % 3;
  if (index > count.value - rest - 1) {
    return `md:col-span-${12 / rest}`;
  }
  return "md:col-span-4";
}

This function returns md:col-span-4 all the time, except:

  • md:col-span-6 for the last 2 items with a (3 x n) + 2 count,
  • md:col-span-12 for the last item with a (3 x n) + 1 count.

Here's a proof of concept (haven't used typescript or <script setup>, but the logic is there). I made count a prop so it could be interacted with.

Note: the function is slightly modified in the sandbox because I've used v-for="n in count", which is 1-based, not 0-based.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the answer. but there is a little tweak in my question sorry for not being not clear. i have reposted my question.
@Sanket, wouldn't <Layout v-for="n in 4" :key="n" :count="8" /> achieve just that? You can pass the global index along to <Layout />, if you need it. See it here.
For convenience, I moved the list wrapper elements to a different component: <LayoutWrapper /> and implemented times in parent. But other than that, it's pretty much the same thing, no?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.