how to add :key in v-for with multiple divs - javascript

I want to make v-for loop without any html element so I decided to use <template as parent. I don't know to assign :key for this loop. I can't assign it to template and to every div inside loop. Any ideas?
<template
v-for="{ id, text, option, percentage, value } in reports"
>
<div class="table-row__index">
{{ id }}
</div>
<div class="table-row__title">
<p>{{ text }} - <strong>{{ option }}</strong></p>
</div>
<div class="table-row__info">
{{ percentage }}%
</div>
<div class="table-row__info">
{{ value }}
</div>
</template>

As a good practice we should always have a parent element inside. But due to your constraints, it's okay to use for loop on template as given in official docs
https://v2.vuejs.org/v2/guide/list.html#v-for-on-a-lt-template-gt
In this case, any keys have to be added to child elements/components and this is what officially recommended.
See this example and please add keys to your div's inside template.
new Vue({
el: '#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<template v-for="n in 5">
<span :key="'number' + n">{{ n }}</span>
<span :key="'dot' + n">. </span>
</template>
</div>

you just can't have the for loop in your template. The for loop directive is only allowed to be inside the first child component ( or root component) inside your template.
Here is an example of how you can render your loop:
<template>
<div class="cant-have-for-loop-this-is-the-root-component">
<div v-for="{ id, text, option, percentage, value } in reports" :key="{id}">
<div class="table-row__index">
{{ id }}
</div>
<div class="table-row__title">
<p> {{ text }} - <strong>{{ option }}</strong></p>
</div>
<div class="table-row__info">
{{ percentage }}%
</div>
<div class="table-row__info">
{{ value }}
</div>
</div>
</div>
</template>
This runs soomthly, and with no hesitations. And renders with no styling as this screenshots depicts:
Hope this answers what you want to achieve.

Related

Is it possible to assign the hash(#) automatically in angular?

Is there any way where I can assign the hash(#) automatically to the elements inside an ngfor?
<div *ngFor="let note of notes; index as i">
<h3 #[note][i]>
{{ note }}
</h3>
</div>
The result I would expect would be something like this:
<div>
<h3 #note11>
note1
</h3>
</div>
<div>
<h3 #note122>
note12
</h3>
</div>
<div>
<h3 #note153>
note15
</h3>
</div>
You can use the index variable to automatically assign a unique id to each element in the ngFor loop. Here's an example:
<div *ngFor="let note of notes; index as i">
<h3 id="note{{i}}">
{{ note }}
</h3>
</div>
This will give each element an id of "note0", "note1", "note2", etc.
Regarding using #, it is not possible to use it in such a way. The # symbol is used to create a template reference variable, you can use it like <h3 #myNote>{{ note }} and you can access the element using myNote in your component.
Try this:
<div *ngFor="let note of notes; index as i">
<h3 #{{note}}{{i}}>
{{ note }}
</h3>
</div>
Note:
This would do your work but # is used to create template reference.

Can you access component slot data from parent

I am trying to get the rangeText data into div outside of the component block for https://innologica.github.io/vue2-daterange-picker/advanced/#slots-demo but it only seems to appear when used in a slot.
I am trying to update the selectDateButtonText text after user selects dates.
Many thanks
<template>
<div v-click-outside="hideCalendarDropdown" class="select-dates">
<button #click="filterCalendarIsActive = !filterCalendarIsActive" :class="{ 'is-active': filterCalendarIsActive }" class="select-dates__button fw-lt-sm">{{ selectDateButtonText }}</button>
<div :class="{ 'is-active': filterCalendarIsActive }" class="calendar-wrapper">
<date-range-picker #finish-selection="datesSelected()"
v-model="dateRange"
:minDate="minDate"
:maxDate="null"
:singleDatePicker="singleDatePicker"
:opens="opens"
:showDropdowns="showDropdowns"
:autoApply="autoApply"
:ranges="ranges"
>
<div slot="footer" slot-scope="data" class="date-range-picker-footer">
{{ data.rangeText }}
<button class="clear-dates" #click="clearDate()" type="button"> Clear </button>
</div>
</date-range-picker>
</div>
</div>
</template>
Got it.
Had to $refs the component
datesSelected() {
this.selectDateButtonText = this.$refs['picker'].rangeText;
}

How to increment a loop in Vue

I've got a multi-object array and I'd like to have it loop through a particular group of objects.
This is my code so far
<template>
<div>
<h1>My Test App</h1>
<button v-on:click="getHockeyData">Get Team Data</button>
<div v-for="hockeyData in hockeyDataList" :key="hockeyData.id" >
<p>{{ hockeyDataList.teams[0].roster.roster[1].person.fullName }}</p>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: "Weather",
data() {
return {
hockeyDataList: []
};
},
methods: {
getHockeyData() {
axios.get("https://statsapi.web.nhl.com/api/v1/teams/21?expand=team.roster").then(response => (this.hockeyDataList = response.data));
}
}
};
</script>
I know the loop won't work in it's current state. The portion of my output within the loop that I need to increment is roster[1] - I'm new to Vue so not sure how to use the v- commands to increment that 1 until there are no more instances of it.
Any help or feedback would be greatly appreciated!
Just loop over the others, really you want to start from teams as that's the way the JSON is structured
Example using various parts of the JSON, view the file for others.
<div v-for="team in hockeyDataList.teams" :key="team.id">
<h1>{{ team.name }}</h1>
<div>{{ team.venue.name }}, {{ team.venue.city }}</div>
<div>Created in: {{ team.firstYearOfPlay }}</div>
<div>Division: {{ team.division.name }} - Conference: {{ team.conference.name }}</div>
<h2>Roster</h2>
<div v-for="player in team.roster.roster" :key="team.id + '-' + player.person.id">
<h3>{{ player.person.fullName }}</h3>
<div>
Number: {{ player.jerseyNumber }} - Position: {{ player.position.name }} {{ player.position.type }}
</div>
</div>
</div>
<div v-for="team in hockeyDataList.teams" :key="team.id" >
<p v-for="roster in team.roster.roster :key="roster.id">
{{ roster.person.fullName }}
</p>
</div>
It's not necessary, but if you want to, you can get index in a v-for as well:
<div v-for="(team, index) in hockeyDataList.teams" :key="team.id" >
<p>
{{ hockeyDataList.teams[index].roster.roster[1].person.fullName }}
</p>
</div>
v-for increments the index automatically for you. The problem is that the api returns a json and not an array we can iterate on. By looking at the api response, we can see that teams is the array we can iterate on.
<v-for="(team, i) in hockeyDataList.teams" :key="i">
where index automatically increments until the end of list. We can then iterate through the roster.
<v-for="(roster, j) in team.roster.roster" :key="j">
Putting it all together
<div v-for="(team, i) in hockeyDataList.teams" :key="i">
<div v-for="(roster, j) in team.roster.roster" :key="j">
<p>{{ hockeyDataList.teams[i].roster.roster[j].person.fullName }}</p>
</div>
</div>

How to loop through unknow number of nested json object in Angular with ngFor?

I'm trying to display all the reply from this json :
https://www.reddit.com/r/AskReddit/comments/k8w43d/people_with_the_last_name_pepper_who_have.json
So, depending of the post im loading and the reply, my number of children will differ. How can I loop throught it until I reach the last reply with children (body[2].data.children) ?
Like this :
<div class="replies-box" *ngFor="let reply of comments.body[1].data.children">
<div class="reply-header">
<p class="reply-author"><b>From</b> : {{ reply.data.author }}</p>
<p class="reply-send"><b>Send</b> : {{ this.getDateReply(reply.data.created_utc) }}</p>
</div>
<div class="text-first-reply" [innerHTML]="this.getHtmlDecode(reply.data.body_html)">
</div>
</div>
I have only the first level of reply, is there a way to simply loop through them all ?
Thanks in advance.
I would use a recursion type of approach.
Develop a app-comment component and if comment has children, loop over the children and display the app-comment. That way it will loop over the comments until no more children
<div *ngIf='comment'>
<span *ngIf='comment.kind; else showComment'>Kind: {{ comment.kind }}</span>
<ng-template #showComment>
<span>{{ comment }}</span>
</ng-template>
<div>
<app-comment *ngFor='let child of comment.data?.children' [comment]='child'> </app-comment>
</div>
</div>
See this sample illustration
Simply use ngFor inside ngFor with help of ng-container (will not create extra dom elements)
<div class="replies-box">
<ng-container *ngFor="let commentBody of comments.body">
<ng-container *ngFor="let reply of commentBody.data.children">
<div class="reply-header">
<p class="reply-author">
<b>From</b> : {{ reply.data.author }}
</p>
<p class="reply-send">
<b>Send</b> : {{ this.getDateReply(reply.data.created_utc) }}
</p>
</div>
<div class="text-first-reply" [innerHTML]="this.getHtmlDecode(reply.data.body_html)">
</div>
</ng-container>
</ng-container>
</div>

Increase variable in ng-repeat

Hello I am a new in angular js. I want to count in ng-repeat like this :
<div ng-repeat="people in peoples">
{{ numberPeople++ }}. {{people.name}}
<div ng-repeat="repeople in people.families">
{{ numberPeople++ }}. {{repeople.name}}
</div>
</div>
<div ng-repeat="otherpeople in otherpeoples">
{{ numberPeople++ }}. {{otherpeople.name}}
</div>
{{ numberPeople }}
</div>
numberPepple will increase in each ng-repeat
I see many question they said use $index but i use many ng-repeat
You can use ng-init.
Tyr this:
<div ng-repeat="people in peoples" ng-init="numberPeople=numberPeople+1">
{{ numberPeople }}. {{people.name}}
<div ng-repeat="repeople in people.families" ng-init="numberPeople=numberPeople+1">
{{ numberPeople }}. {{repeople.name}}
</div>
</div>
<div ng-repeat="otherpeople in otherpeoples" ng-init="numberPeople=numberPeople+1">
{{ numberPeople }}. {{otherpeople.name}}
</div>
{{ numberPeople }}
</div>
You can use angular.forEach in JS file and set it in the model. Use that model in the HTML code.
I'm guessing the ++ is not working, in your controller add $scope.numberPeople = 0; at the top and it will initialize the scope variable as an integer type and assign 0 to it. Then you can use ++.

Categories

Resources