v-for in array route // vuejs - javascript

In the attached screen shot I want to get to the content. I'm trying to reach it with element.comments.content but doesn't work, see the code below:
<div class="fil-actualites-container">
<div class="posts" v-for="(element, index) in postArray" :key="index">
<p>{{ element.title }}</p>
<p>{{ element.content }}</p>
<p>{{ element.likes.length }}</p>
<button #click="addLike(element._id)">Add Like</button>
<br />
<input
type="text"
v-model="contentComment"
#keydown.enter="addComment(element._id)"
placeholder="add Comment"
/>
<p>{{ element.comments.content }}</p>
</div>

comments is an array ([]) within the array of posts.
Therefore you need to loop over that to access the values within. I don't know your exact use case but something like this:
<div class="fil-actualites-container">
<div class="posts" v-for="(element, index) in postArray" :key="index">
<div v-for="(comment, i) in element.comments" :key="`comment-${i}`">
<p>{{ comment.title }}</p>
<p>{{ comment.content }}</p>
<p>{{ comment.likes.length }}</p>
<button #click="addLike(comment._id)">Add Like</button>
<br />
<input
type="text"
v-model="contentComment"
#keydown.enter="addComment(comment._id)"
placeholder="add Comment"
/>
<p>{{ comment.content }}</p>
</div>
</div>
I have added another loop within your existing one to loop through the comments and access the values.

The comments are related to the posts. A post can have several comments. If you now iterate through the posts, you will come to the key comments. Comments must also be looped through at this point. The oneToMany relationship is the reason why you have to include a comment loop within your post loop. This gives you access to every single comment. I hope this helps you without writing a lot of code.

Related

How to solve error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key in Vuejs?

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app-gridview">
<div>
<button class="button" v-on:click="switchView()"><span>{{ buttonSwitchViewText }}</span></button>
<button class="button" v-on:click="switchData()"><span>{{ buttonSwitchDataText }}</span></button>
</div>
<div v-bind:class="[ isGridView ? 'grid-wrapper' : 'list-wrapper' ]">
<div class="grid-row" v-if="isGridView">
<div class="grid-header" v-for="name in gridData.columns">{{ name }}</div>
</div>
<!-- GridView structure -->
<div v-if="isGridView" class="grid-row" v-for="row in gridData.data">
<div class="list-row-item" v-for="name in gridData.columns">
<div>{{ row[name] }}</div>
</div>
</div>
<!-- ListView structure -->
<div v-if="!isGridView" class="list-row" v-for="row in gridData.data">
<img v-bind:src="row.ImagePath" class="list-image" />
<div class="list-property">
<div class="list-row-item" v-for="name in gridData.columns">
<div class="list-property-name">{{ name }}</div>
<div>{{ row[name] }}</div>
</div>
</div>
</div>
</div>
</div>
Getting error as
error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key
How can I solve this issue, With some reference, I come to know we need to pass v-bind-key for the value, But not sure how to pass it.
Whenever we are using v-for in vuejs, we need to pass a unique value which is key which helps in properly rendering the components whenever the loop runs.
You can pass it like <div class="list-row-item" v-for="(name, index) in gridData.columns" :key="index">
The value of the key needs to be unique.
You should use uniq index inside your loop. Look hear https://v2.vuejs.org/v2/guide/list.html
<div v-if="!isGridView" class="list-row" v-for="(row, index) in gridData.data" :key="index">

boostrap issue in single page

I've been trying to create a card component for array elements and on clicking the header of the card, a modal should be opened showing the info of that particular array element. However on clicking on the header, multiple modals are opened, in essence even if I click on a header of a particular element, all the array elements modals open up. How do I make it so that only the modal of that particular modal opens up? I'm using vue bootstrap
<div
v-for="(value,key,index) in flowers"
:key="value"
class="card"
>
<div v-b-modal.modal-1 class="card-header" >
<div>
{{ value.name }}
</div>
<b-modal id="modal-1" title="Flowers">
<p class="my-4" v-for="item in value.petals" :key="item">{{item}}</p>
</b-modal>
</div>
</div>
You're assigning the same id to all your modals. Meaning you're creating a bunch of modals with the id modal-1, and then clicking the header you're telling your code to open all modals with the id modal-1.
You need to give each modal a unique id.
In the below snippet I'm using the key, but if you have a unique value for each entry, i would suggest you use that instead.
<div
v-for="(value, key, index) in flowers"
:key="value"
class="card"
>
<div v-b-modal:[`modal-${key}`] class="card-header" >
<div>
{{ value.name }}
</div>
<b-modal :id="`modal-${key}`" title="Flowers">
<p class="my-4" v-for="item in value.petals" :key="item">{{item}}</p>
</b-modal>
</div>
</div>
I think all your modals have the same id id="modal-1". You can try to use the key of the top v-for like an id, something like this id="modal-{{key}}.
This is an example:
<tbody>
<tr v-for="item in items" v-on:click="select($event)" id="{{ item.ID }}">
<td class="cod">{{ item.ID }}</td><td class="name">{{ item.NAME }}</td><td class="cat">{{ item.CATEGORY }}</td><td class="price">{{ item.PRICE }}</td>
</tr>
</tbody>

show all array with vue.js and bootstrap

Hi with my script i can show only the first reccord because [0]
what should i do to show all reccords ? because sometimes are only one reccord and sometimes many.
<v-tab :title="sitePartGSM[0].serial_no" v-if="sitePartGSM[0]">
<div v-for="siteParts in sitePartGSM">
{{ siteParts.serial_no }}
<div class="description" v-for="item in siteParts.part_attributes">
<small>
<strong>{{item.x_name}}</strong>
{{item.x_value}}
</small>
</div>
</div>
</v-tab>
thanks
hi can use a index inside v-for for example
<div v-for="(siteParts, index) in sitePartGSM">
<v-tab :title="sitePartGSM[index].serial_no" v-if="sitePartGSM[index]">
{{ siteParts.serial_no }}
<div class="description" v-for="item in siteParts.part_attributes">
<small>
<strong>{{item.x_name}}</strong>
{{item.x_value}}
</small>
</div>
</v-tab>
</div>
with this method you can see all records
You can iterate over all your sitePartGSM elements and show them in your v-tab.
When using v-for you should define a :key attribute to improve the rerendering procedure has mentioned in the documentation
<v-tab v-for="siteParts in sitePartGSM" :title="siteParts.serial_no" :key="siteParts.serial_no">
<div>
{{ siteParts.serial_no }}
<div class="description" v-for="item in siteParts.part_attributes" :key="item.x_name">
<small><strong>{{item.x_name}}</strong> {{item.x_value}}</small>
</div>
</div>
</v-tab>

VueJS - Pass slot to child of child component

I have a list and a list_item component that I reuse a lot inside my application. On a simplified form:
contact_list.vue
<template lang="pug">
.table
.table-header.table-row
.table-col Contact
.table-col Info
.table-body
contact-list-item(v-for='contact in contacts',
:contact='contact',
#click='doSomething()')
</template>
contact_list_item.vue
<template lang="pug">
.table-row(#click='emitClickEvent')
.table-col {{ contact.name }}
.table-col {{ contact.info }}
</template>
When I use contact_list inside a specific component, I want to be able to send a slot that will add some new columns to the contact_list_item component. This slot will use data of the specific contact that is being rendered inside that contact_list_item component to generate the new columns.
How could I achieve that? Is using slot the best approach?
Thanks in advance.
Slots are the best approach and you will need to use a scoped slot for the contact-list-item component. I'm not really familiar with pug, so I will use HTML for the example.
In contact-list you would add a slot. Notice in this case that the contact is being passed as a property. This is so we can take advantage of scoped slots.
<div class="table">
<div class="table-header table-row">
<div class="table-col">Contact</div>
<div class="table-col">Info</div>
</div>
<div class="table-body">
<contact-list-item v-for='contact in contacts'
:contact="contact"
#click="doSomething"
:key="contact.id">
<slot :contact="contact"></slot>
</contact-list-item>
</div>
</div>
Then add a slot to the contact-list-item.
<div class="table-row" #click="emitClickEvent">
<div class="table-col">{{contact.name}}</div>
<div class="table-col">{{contact.info}}</div>
<slot></slot>
</div>
Finally, in your Vue template, use the scoped template.
<div id="app">
<contact-list :contacts="contacts">
<template scope="{contact}">
<div class="table-col">{{contact.id}}</div>
</template>
</contact-list>
</div>
Here is a working example. I have no idea what your styles are but notice the id column is now displayed in the contact-list-item.
You can use template for registering slot to the child of child component.
There is also a case when you want to have many named slots.
child.vue
<template>
<div>
<h2>I'm a father now</h2>
<grandchild :babies="babies">
<template v-for="(baby, id) in babies" :slot="baby.name">
<slot :name="baby.name"/>
</template>
</grandchild>
</div>
</template>
grandchild.vue
<template>
<div>
<p v-for="(baby, id) in babies" :key="id">
<span v-if="baby.isCry">Owe...owe...</span>
<slot :name="baby.name">
</p>
</div>
</template>
parent.vue
<template>
<div>
<h2>Come to grandpa</h2>
<child :babies="myGrandChilds">
<button slot="myGrandChilds[2].name">baby cry</button>
</child>
</div>
</template>
Add to #DrSensor's answer.
In Vue3, you should use dynamic slot name.
<template>
<div>
<h2>I'm a father now</h2>
<grandchild :babies="babies">
<template v-for="(baby, id) in babies" #[baby.name]>
<slot :name="baby.name"/>
</template>
</grandchild>
</div>
</template>
To translate several slots one level down conveniently to use the method described at this link, and if you modify it a little, perhaps you will be able to transfer it deeper.

Dynamic change of content better ways. AngularJS 1.6

I have REST service that gives some information for banner. I want to use this information for dynamic change of slider on main page.
So I simply use $http.get to get data, and then interpolation, with some additional ng-if's to check, if there is specific data, to displaying or not some elements.
<div class="main-block" ng-if="locale==='ru'">
<div ng-repeat="slider in restData.result" ng-class="{'active':$first}" class="slide {{ slider.location }}" ng-style="{'background-image':'url({{ slider.url.url }})'}">
<div class="content-block">
<div class="container">
<div class="right-block">
<h2>{{ slider.text1 }}</h2>
</div>
<div class="clearfix"></div>
<div ng-if="slider.text2 || slider.text3 || slider.text4 || slider.text5" class="offer-block" ng-style="{'background':'rgba({{ slider.color }},0.6)'}">
<div class="offer-block__country">{{ slider.text2 }}</div>
<div class="offer-block__name">
{{ slider.text3 }}
</div>
<div class="offer-block__days">
{{ slider.text4 }}
</div>
<div class="offer-block__date">
{{ slider.text5 }}
</div>
</div>
<div class="clearfix"></div>
<a ng-if="slider.link" ui-sref="shell.tourShow({url:'{{ slider.link }}'})" class="orange-btn">
Подробнее
</a>
</div>
</div>
</div>
</div>
But I feel like there must be better way to work with such type of data manipulation, more readable and understandable. Can you please help to find one, or give a little example, how to do it better.
It is relatively good already, the only thing I would change is not to directly map to ng-repeat="slider in restData.result"
but rather create a $scope variable like
$scope.sliders = {};
// in rest request update the local variable with most recent data
// and then use ng-repeat="slider in sliders"

Categories