Home > front end >  Dynamic columns how to seperate styles
Dynamic columns how to seperate styles

Time:11-03

I am trying to create dynamic columns, whenever I have 2,3,4 columns then it's not a problem because these are cards with same styles. I want to be able to have 1 item per row with completely different css than the cards. What's the best way to achieve that?

This is what I've tried so far

<script setup>
import { ref } from 'vue'

const list = ref([
  { title: 'hello', content: 'world'},
  { title: 'hello', content: 'world'},
  { title: 'hello', content: 'world'},
  { title: 'hello', content: 'world'},
  { title: 'hello', content: 'world'},
])

const itemsPerRow = ref('25%')

function toggle(e) {
  itemsPerRow.value = `${e.target.value}%`
}
</script>

<template>
  <select @change="toggle($event)">
    <option value="25">4</option>
    <option value="33">3</option>
    <option value="50">2</option>
    <option value="100">1</option>

  </select>
  <div >
    <div >
      
    
    <div v-for="item in list" >
      {{ item.title }}
    </div>
</div>
  </div>
</template>


<style>
  .items {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
  }
  
  .item {
    flex-basis: v-bind(itemsPerRow);
    border: 1px solid black;
    box-sizing: border-box;
  }
</style>

CodePudding user response:

Working Example

This is just one of many ways you could conditionally render the data based on the number of columns.

Per Vue documentation, you could place the v-for on a template element. And inside use v-if and v-else to render different markup. In this example we check if itemsPerRow == '100%', which indicates that one column is being displayed, and apply different Bootstrap classes.

 <template v-for="item in list"> 
    <div v-if="itemsPerRow == '100%'" >
      <img  src="https://loremflickr.com/320/50/dog">
     <div >
      <h5 >{{item.title}}</h5>
      {{item.content}}
      </div>
    </div>
    <div v-else >
    {{ item.title }}
   </div>
  </template>

Snippet

The snippet differs from the original code since it's an app rather than a component. Selecting 1 column from the dropdown will display a different layout from multiple columns.

const {
  createApp
} = Vue



createApp({
  methods: {},
  watch: {
    itemsPerRow: function(value) {
      document.querySelector(":root").style
        .setProperty("--itemsPerRow", value);
    }
  },
  data() {
    return {
      itemsPerRow: "25%",
      list: []
    }
  },
  mounted() {
    for (let i = 1; i <= 100; i  ) {
      this.list.push({
        title: "Title "   i,
        content: "The quick brown fox jumped over the lazy dog"
      });
    }
  }
}).mount('#app')
:root {
  --itemPerRow: 25%;
}

.container {
  margin: 2rem;
}

.items {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  width: 100%;
}

.item {
  flex-basis: var(--itemsPerRow);
  border: 1px solid black;
  box-sizing: border-box;
  padding: 0.25rem;
}
<div id="app">
  <div >

    <select v-model="itemsPerRow" >
      <option value="25%">4 columns</option>
      <option value="33%">3 columns</option>
      <option value="50%">2 columns</option>
      <option value="100%">1 column</option>
    </select>

    <div >
      <template v-for="item in list"> 
        <div v-if="itemsPerRow == '100%'" >
          <img  src="https://loremflickr.com/320/50/dog">
         <div >
          <h5 >{{item.title}}</h5>
          {{item.content}}
          </div>
        </div>
        <div v-else >
        {{ item.title }}
       </div>
      </template>
    </div>
  </div>
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>

<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">

CodePudding user response:

If I understood you correctly, you can use some event (click in demo) and set style:

const { ref } = Vue
const app = Vue.createApp({
  setup() {
    const list = ref([
      { title: 'hello', content: 'world'},
      { title: 'hello', content: 'world'},
      { title: 'hello', content: 'world'},
      { title: 'hello', content: 'world'},
      { title: 'hello', content: 'world'},
    ])
    const itemsPerRow = ref('25%')
    function toggle(e) {
      itemsPerRow.value = `${e.target.value}%`
    }
    const index = ref(null)
    const setIndex = (i) => {
      index.value = i
    }
    const setStyle = (i) => {
      const selected = index.value === i ? itemsPerRow.value : `25%`
      return `flex-basis: ${selected}`
    }
    return {
      list, itemsPerRow, toggle, setIndex, index, setStyle
    };
  },
})
app.mount('#demo')
.items {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  width: 100%;
}

.item {
  border: 1px solid black;
  box-sizing: border-box;
}
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
  <select @change="toggle($event)">
    <option value="25">4</option>
    <option value="33">3</option>
    <option value="50">2</option>
    <option value="100">1</option>
  </select>
  <div >
    <div >
      <div v-for="(item, i) in list"  :key="i" @click="setIndex(i)" :style="setStyle(i)">
        {{ item.title }}
      </div>
    </div>
  </div>
</div>

  • Related