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>