Create new row for every 3 items Vue.js - javascript

Basically the code works fine but I am not able to change the order of the elements. At the moment the result looks like this:
But actually I would like it like this:
My code Looks like this:
<template>
<div class="home">
<el-container>
<el-row v-for="story of chunkedItems" :key="story.id">
<el-col v-for="item of story" :key="item.id">
<el-card>
<div>{{ item.title }}</div>
<div>{{ item.text }}</div>
</el-card>
</el-col>
</el-row>
</el-container>
</div>
</template>
computed: {
chunkedItems() {
return this.$_.chunk(this.stories, 3);
},
},
Any suggestion is appreciated.

Remove the chunk and use :span="8" instead.
<template>
<div class="home">
<el-container>
<el-row>
<el-col :span="8" v-for="item of stories" :key="item.id">
<el-card>
<div>{{ item.title }}</div>
<div>{{ item.text }}</div>
</el-card>
</el-col>
</el-row>
</el-container>
</div>
</template>
computed: {
},

Related

How to iterate on a collection (array) of objects in Nuxt?

I'm building a small project where it has a component in it, I should render the data from the API.
Here is my code:
<template>
<div>
<p v-if="$fetchState.pending">Fetching products...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<h1>Nuxt products</h1>
<ul>
<li
v-for="(product, key) of product"
:key="product.id"
:img="product.img"
>
{{ product.description }}
</li>
</ul>
<button #click="$fetch">Refresh</button>
</div>
</div>
</template>
<script>
export default {
async fetch() {
this.products = await this.$axios("https://dummyjson.com/products");
},
};
</script>
and here is the error code:
Property or method "product" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option or for class-based components, by initializing the property
This works
<template>
<div>
<p v-if="$fetchState.pending">Fetching products...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<h1>Nuxt products</h1>
<ul>
<li v-for="product in products" :key="product.id" :img="product.img">
{{ product.description }}
</li>
</ul>
<button #click="$fetch">Refresh</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
products: [],
};
},
async fetch() {
const response = await this.$axios.$get('https://dummyjson.com/products')
this.products = response.products
},
}
</script>
You need v-for="product in products" as explained here: https://vuejs.org/guide/essentials/list.html
Also, regarding the the network request
We can see that as usual, the actual data is inside data, hence you can use the $get shortcut: https://axios.nuxtjs.org/usage#-shortcuts
Then you need to access the products field to have the data to iterate on. Using the Vue devtools + network tab greatly helps debugging that one!
so the answer is i missed putting the data as #kissu has mentioned above
<template>
<div>
<p v-if="$fetchState.pending">Fetching products...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<h1>Nuxt products</h1>
<ul>
<li v-for="product in products" :key="product.id">
{{ product.description }}
{{ product.images }}
</li>
</ul>
<button #click="$fetch">Refresh</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
products: [],
};
},
async fetch() {
const response = await this.$axios.$get("https://dummyjson.com/products");
this.products = response.products;
},
};
</script>

Vue v-select problem with v-slot not showing text

I'm trying to display custom text in v-select options by slots.
Template:
<v-select v-model="dLevelSelected" :items="dLevels" solo>
<template slot="item" slot-scope="data">
<span>{{data.description}}</span>
</template>
</v-select>
Script:
data () {
return {
dLevelSelected: null,
dLevels: [{id:1, value: 1, description: 'Level1'}, {id:2, value: 2, description: 'Level2'}]
}
}
With this, when you open the v-select the two registers of dLevels are appearing as boxes but with any text. It seems like the data.description is being evaluated like data.undefined
Thanks!
slot and slot-scope are deprecated as of Vue 2.6.0.
The new slot syntax combines those two props into v-slot, so the equivalent item slot is:
<template v-slot:item="scope">
<span>{{ scope.item.description }}</span>
</template>
Note the scope contains an item property that can be used to access description. You can use object destructuring to simplify that to:
<template v-slot:item="{ item }">
<span>{{ item.description }}</span>
</template>
Similarly, you'll probably want a custom selection slot that renders the appearance of the selected item:
<template v-slot:selection="{ item }">
<span>{{ item.description }} ({{ item.value }})</span>
</template>
The final template should look similar to this:
<v-select v-model="dLevelSelected" :items="dLevels" solo>
<template v-slot:item="{ item }">
<span>{{ item.description }}</span>
</template>
<template v-slot:selection="{ item }">
<span>{{ item.description }} ({{ item.value }})</span>
</template>
</v-select>
demo

Rendering VUE slot only if content matches specific value

I have two routes that render the same component but with different data coming from an API.
This component has a child component called <base-section> that has a v-if directive that checks if a specific slot has content or not (because if it has no content, I don't want the slot to show).
However, there might be more than one instance of this child component on the same parent component, and therefore, if one of the instances has content in the slot, but the other one doesn't, VUE will automatically assume that all slots have content.
Therefore, I would like to know if there is any way of checking the specific slot content of each instance and then compare it with the data coming from the API. Please find my code below:
Parent component (Content.vue)
<template>
<base-section
v-for="entry in this.entries"
:key="entry.title"
lang="lang-markup"
:title="entry.title"
>
<template v-slot:content>
<span v-html="entry.content"></span>
</template>
<template v-slot:examples>
<div v-html="entry.examples"></div>
</template>
<template v-slot:code>
{{ entry.code }}
</template>
</base-section>
</template>
Child component (BaseSection.vue)
<template>
<hr class="my-6" />
<h4 class="text-salmon">{{ title }}</h4>
<section>
<div class="section-sm txt-justify" v-if="this.$slots.content">
<slot name="content"></slot>
</div>
<span class="medal bg-light text-dark code-medal">Examples</span>
<div class="section-sm border-light-1 mb-3">
<slot name="examples"></slot>
</div>
<span class="medal text-dark code-medal">Code</span>
<pre :class="lang + ' border-light-1 bg-light'">
<code><slot name="code"></slot></code>
</pre>
</section>
</template>
The data coming from the API follows this structure:
getData() {
const url = this.apiUrl + this.$route.name + this.apiToken
fetch(url)
.then((collection) => collection.json())
.then((collection) => {
const entries = [];
this.entries = [];
for (const id in collection.entries) {
if (collection.entries[id].Version === this.byteVersion) {
entries.push({
title: collection.entries[id].Title,
content: collection.entries[id].Content,
examples: collection.entries[id].Examples,
code: collection.entries[id].Code,
});
}
}
this.entries = entries;
});
}
Thank you very much for your help!
Regards,
T.
Maybe you can pass the "entry.content" into your BaseSection component. and v-if the entryContent.
Parent component (Content.vue)
<template>
<base-section
v-for="entry in this.entries"
:key="entry.title"
lang="lang-markup"
:title="entry.title"
:entryContent="entry.content"
>
<template v-slot:content>
<span v-html="entry.content"></span>
</template>
<template v-slot:examples>
<div v-html="entry.examples"></div>
</template>
<template v-slot:code>
{{ entry.code }}
</template>
</base-section>
</template>
Child component (BaseSection.vue)
<div class="section-sm txt-justify" v-if="entryContent">
<slot name="content"></slot>
</div>
Or you can v-if your content template
<template v-slot:content v-if="entry.content">
<span v-html="entry.content"></span>
</template>

Polymer DOM-repeat content depending on received data

I have made a DOM-repeat that recieves multiple types of data.
Now I want the DOM-repeat to only show the items related to that type.
Is it possible to do this and how would I be able to achieve this?
When the item.Type is Zone I want it to display the item.Name and item.ZoneID
when the item.Type is Building I want it to display the item.BuildingID, item.Address1 and item.Address2
This is my code:
<template is="dom-repeat" items="[[data]]">
<paper-card id="departmentspaperContainer2">
<div class="card-content">
<h3>Type: {{item.Type}}</h3>
<hr/>
<h4>Name: {{item.Name}}</h4>
<h4>BuildingID: {{item.BuildingID}}</h4>
<h4>ZoneID: {{item.ZoneID}}</h4>
<h4>Address1: {{item.Address1}}</h4>
<h4>Address2: {{item.Address2}}</h4>
</div>
</paper-card>
</template>
Something similar to what 'HakanC' is proposing, but differently, you can use the dom-if and bind the response of your filter function :
Here is a working jsfiddle (to use in chrome)
<dom-module id="os-test">
<template>
<template is="dom-repeat" items="{{data}}">
<paper-card id="departmentspaperContainer2">
<div class="cardContent" type="{{item.Type}}">
<h3>Type: [[item.Type]]</h3>
<hr/>
<template is='dom-if' if='{{showZone(item.Type)}}'>
<h4>Name: [[item.Name]]</h4>
<h4>ZoneID: [[item.ZoneID]]</h4>
</template>
<template is='dom-if' if='{{showBuilding(item.Type)}}'>
<h4>BuildingID:[[item.BuildingID]]</h4>
<h4>Address1: [[item.Address1]]</h4>
<h4>Address2: [[item.Address2]]</h4>
</template>
</div>
</paper-card>
</template>
</template>
</dom-module>
<script>
class OsTestElement extends Polymer.Element {
static get is() {
return 'os-test';
}
static get properties() {
return {
data: {
type: Array,
value: () => {
return [
{
Type:"Zone",
Name:"valueName1",
BuildingID:"valueBuildingID1",
ZoneID:"valueZoneID1",
Address1:"valueAddress11",
Address2:"valueAddress21",
},
{
Type:"Zone",
Name:"valueName2",
BuildingID:"valueBuildingID2",
ZoneID:"valueZoneID2",
Address1:"valueAddress12",
Address2:"valueAddress22",
},
{
Type:"Building",
Name:"valueName3",
BuildingID:"valueBuildingID3",
ZoneID:"valueZoneID3",
Address1:"valueAddress13",
Address2:"valueAddress23",
},
{
Type:"Building",
Name:"valueName4",
BuildingID:"valueBuildingID4",
ZoneID:"valueZoneID4",
Address1:"valueAddress14",
Address2:"valueAddress24",
}
]
}
}
}
}
showZone(item) {
return (item==="Zone");
}
showBuilding(item) {
return (item==="Building");
}
}
window.customElements.define(OsTestElement.is, OsTestElement);
</script>
You may use dom-if into dom-repeat as fallow.
<template is="dom-repeat" items="[[data]]">
<paper-card id="departmentspaperContainer2">
<div class="card-content">
<h3>Type: {{item.Type}}</h3>
<hr/>
<h4>Name: {{item.Name}}</h4>
<template is='dom-if' if='{{_show(item.Type)}}'>
<h4>ZoneID: {{item.ZoneID}}</h4>
</template>
<template is='dom-if' if='{{!_show(item.Type)}}'>
<h4>BuildingID: {{item.BuildingID}}</h4>
<h4>Address1: {{item.Address1}}</h4>
<h4>Address2: {{item.Address2}}</h4>
</template>
</div>
</paper-card>
</template>
....
_show(it){
return (it === "Zone");
}
With above logic should solve the problem.

How to break a v-for loop in vuejs

I have a code segment that i have mentioned below. I have used vuejs with vuetifyjs.
<v-data-table v-bind:headers="headers" v-bind:items="uniqueSubjects">
<template slot="items" slot-scope="props">
<td class="text-xs-center">{{ props.index+1 }}</td>
<td class="text-xs-center">{{ month[new Date(props.item.daily_date).getMonth()] }},{{ props.item.student_id }}</td>
<td class="text-xs-center">{{ props.item.subjects.subject_name }}{{ props.item.subjects.id }}</td>
<template v-for="n in 31">
<template v-for="(mark,index) in resultsList">
<template v-if="new Date(mark.daily_date).getDate() == n && mark.subject_id == props.item.subject_id && mark.student_id == props.item.student_id">
<td class="text-xs-center">
{{ mark.daily_marks }}
</td>
</template>
<template v-else-if="index>=resultsList.length-1">
<td class="text-xs-center">-</td>
</template>
</template>
</template>
</template>
<template slot="pageText" slot-scope="{ pageStart, pageStop }">
From {{ pageStart }} to {{ pageStop }}
</template>
</v-data-table>
I want to break my <template v-for="(mark,index) in resultsList"> loop when the internal v-if condition is true.
Here i want to search the inner loop from first to last.I want to break the loop if the data is matched depending on the given condition.and then i want to do it again and again.
How can I do that? Any help would be appreciated.
Thanks in advance.
There is no way to break v-for. It is better to create a computed property in your component and filter your data there to pass only needed data to v-for.
For example:
// ... your component code
computed: {
validResultsList() {
return this.resultsList/* ... your filtering logic ... */;
}
}
// ... your component code
And then in your template:
<template v-for="(mark,index) in validResultsList">

Categories