How do I retrieve the value of my key button and row in v-for using Vue.js? - vue.js

I am new to Vue.js and I trying to learn now to use it. I have 3X3 structure of buttons
I have the following sample code:
<template v-for="row in 3">
<div class="row" :key="row">
<button #click="nextPlayer(button, row)" v-for="button in 3" :key="indexByrow(button, row)" :value="squares[indexByrow(button, row)]" class="square" style="width:40px;height:40px;"></button>
</div>
</template>
When I click, I want to pass the button and row to nextPlayer(button, row), and the indexByrow(button, row) to use those values in the methods, but I don't seem to have any values. My main goal is to change the value name when I click on it.

You need to make the below changes
<template v-for="(row, indx) in 3">
<div class="row" :key="indx">
<button #click="nextPlayer(button, row)" v-for="(button, indexer) in 3" :key="indexer" :value="squares[indexByrow(button, row)]" class="square" style="width:40px;height:40px;"></button>
</div>
</template>
Not sure if indexByrow is a computed property or method.
You need to modify the logic in indexByrow as well based on the above changes

Related

How do I take the value of my v-for and step them in mounted() and data() in vue.js, and i have a problem with combobox, i'll explain below?

basically what I'm trying to do is, I get the DateTime coming from my database along with some information of a possible meeting, if people are busy, they will have the option to extend that time through a combobox that pulls a enum in my backend which has values ​​in milliseconds, description and id. As I get these values ​​coming from my enum, I can extend the meeting, but I did this validation on the frontend through a function... where I get the value of the combobox, and add it to the dateTime coming from the BE, however, I can't change the database (legacy) to add a field to save the enum, and that's why I had to make an adapted function in the frontend, and the extension method is hardcoded and doesn't have a field in the BE it replicates the same combobox for all. pointing out that I can't pull the data still coming from my v-for to mounted() or data().
Please help me. I'm using Primevue.
i tried to catch the index/code coming from the v-for by #click the dropdown by creating the function in mounted(), but without success. When trying to manipulate this data, it returns me an undefined value enter image description here
my v-for loop
`<div
class="mt-2"
v-for="(item, index) in listaAlarme"
:key="index">
<!-- {{ item.codigo }}
{{ index }} :{{ listaAlarme[index].referencia }} -->
<Card class="cardContainer">
<template #content>
<div class="formgrid grid">
<UnoFormField
id="dateTimeReference"
:cols="4"
label="Date and Time">
<UnoFormCalendar
v-model="listAlarm[index].reference"
#click="handleAlterTime(index)"
:withTime="true" />
</UnoFormField>
<UnoFormField
id="extended"
:cols="3"
label="Extended">
<Dropdown
v-model="typeActivitiesExtend"
:options="typeActivitiesExtendList"
option-label="description"
option-value="milliSeconds"
placeholder="Extended"
:class="{
'w-full': true,
}"
class="p-dropdown-uno-trigger-black"></Dropdown>
</UnoFormField>
<UnoFormField
id="contact.name"
:cols="3">
<div class="phoneIcon">
<fa-icon
icon="phone"
#click="handleCall" />
</div>
</UnoFormField>
</div>
</template>
<template #footer>
<div class="formgrid grid">
<!-- <div class="flex"> -->
<UnoFormField
id="meeting"
:cols="3">
<Button
icon="pi pi-search"
class="p-button-uno-black"
#click="handleMeeting"></Button>
</UnoFormField>
<UnoFormField
id="description"
:cols="3">
<p class="text">
{{ listAlarm[index].shortDescription }}
</p>
</UnoFormField>
<div class="iconButtons">
<fa-icon
icon="ban"
class="banIcon"
#click="excludeItem" />
<fa-icon
icon="check"
class="checkIcon"
#click="onBtnSave" />
</div>
<!-- </div> -->
</div>
</template>
</Card>
`
the UnoFormField, is a label as you can see, that me return the label name and fied col just for display de fields with a size col in template
my function to extend the hours in methods:
i'm try to catch the value of datatime in v-for
`

Vue Component that Can Override What Child Renders Dynamically

I am working on a component (InfoCard) that should be able to render any number of fields passed into it with a 'fields' prop, as an array of json objects with a name, value, and some styling options. For certain fields, I want to be able to override what component is used to render, but do it from the parent (Table) rather than inside the InfoCard component, as it should be generic. My first thought was to use a <component :is='field.component'></component>, where it will render as plaintext if field.component is not defined, but to my understand it will be difficult to pass in any potential children necessary for the <component/>. My second thought is to use named slots from within the parent, but I don't think this is possible either in a good way. I'll show my current code.
In my example, I want to be able to detect if the field being rendered is 'status', and if it is, use a different rendering mechanism than displayValue(attribute), without hardcoding it inside InfoCard; I want the parent to be able to override this rendering conditionally. Is there a way to do this in Vue? Thanks
From Table, where data.records is an array of JSON objects:
<info-card
v-for="(record,index) in data.records"
:key="index"
:fields="record"
>
<div v-for="key in Object.keys(record)" :key="key">
<template v-if="field.name=='status'" v-slot:[`${field.name}_value`]>
<p> Field is status !</p>
</template>
</div>
</info-card>
From InfoCard:
<template>
<el-col
:lg="3"
:md="3"
:sm="3"
:xs="3"
v-for="(attribute, index) in fields"
:key="index"
class="attribute"
>
<div
#click="$emit('fieldClicked', attribute)"
>
<el-row
:class="`mid-gray f6 clipped fw5-ns m-b-10 ${attribute.nameClasses}`"
:title="displayName(attribute)"
:style="attribute.nameStyle?attribute.nameStyle:''"
>
<slot
v-if="Object.keys($scopedSlots).includes(`${attribute.name}_name`)"
:name="$scopedSlots[`${attribute.name}_name`]"
>
</slot>
<div v-else>
{{ displayName(attribute) }}
</div>
</el-row>
<el-row
:class="`mid-gray f6 clipped fw5-ns m-b-10 ${attribute.valueClasses}`"
:title="displayValue(attribute)"
:style="attribute.valueStyle?attribute.valueStyle:''"
>
<slot
v-if="Object.keys($scopedSlots).includes(`${attribute.name}_value`)"
:name="$scopedSlots[`${attribute.name}_value`]"
>
</slot>
<div v-else>
{{ displayValue(attribute) }}
</div>
</el-row>
</div>
</el-col>
</template>

Pass row.item.attribute value to a modal with Bootstrap Vuejs

I have a table where in the last column there is a button that pressing it pops-up a modal with some information and actions to do.
To this modal I want to pass a value from the table (from a specific cell of each row) but the modal shows always the cell value from the last row of the table (it is like it considers the whole table as one row).
To do some test I wrote the attribute to be appeared on the button title ,and so far it works well (to each button it appears the correct attribute of each row).
It seems that in the next level (inside the modal) there is a misunderstanding and whichever modal opens it presents always the cell value of the last row.
table
modal
<b-table
sticky-header
selectable
select-mode="single"
selected-variant="success"
w-auto
show-empty
small
stacked="md"
id="eventdataTable"
striped
hover
responsive
:items="items"
:fields="event_columns"
:per-page="perPage"
:current-page="currentPage"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
:sort-direction="sortDirection"
:filter="filter"
:filterIncludedFields="filterOn"
#filtered="onFiltered"
>
<template v-slot:cell(nearby_venues)="row">
<div>
<b-button
variant="info"
class="text-center"
size="sm"
#click="show1 = true"
v-b-modal="'modal1'"
>Nearby Venues {{ row.item.api_id }}
</b-button>
<b-modal
id="modal1"
ok-variant="info"
v-model="show1"
size="sm"
title="Nearby Venues"
> {{ row.item.api_id }} *This appears correct*
<p align="left">Choose Venues close to</p>
<b-form-select
v-model="userdata.eventApiId"
class="mb-3"
>
<template slot="first">
<option :value="row.item.api_id">
{{ row.item.api_id }} *This appears wrong -the value of the column cell from the last row*
</option>
</template>
</b-form-select>
<label
class="mr-sm-3"
for="venue-category-selection"
></label>
<b-form-select
class="mb-2 mr-sm-2 mb-sm-0"
v-model="userdata.selectedVenueCategory"
:options="venue_categories"
value-field="id"
text-field="name"
id="venue-category-selection"
size="sm"
></b-form-select>
<hr width="300" align="left" />
<div>
<p align="left">Distance</p>
<label
class="mr-sm-3"
for="event-place-selection"
></label>
<b-form-input
v-model="userdata.distance"
placeholder="distance"
width="5px"
></b-form-input
>km.
<b-button
size="sm"
variant="success"
#click="VenuesFromSelectedEvent"
v-b-toggle.collapse-2
>
Click Here
</b-button>
</div>
</b-modal>
</div>
</template>
</table>
The problem here is that there is a loop in this component going through every row, rendering a new b-modal for each row. The problem is in this part of the code:
```
<b-form-select
v-model="userdata.eventApiId"
class="mb-3">
```
Each time a modal is rendered for a new row, it changes the userdata.eventApiId to the value for the current row. So the userdata.eventApiId will always end up being the api_id for the last row of the table.
One solution would be to change the code so that when the button is clicked, you change the userdata.eventApiId to the row.item.api_id.
I also wouldn't recommend putting the modal in the loop, as you would be creating a lot of hidden modals. I would just have one modal outside of the table that changes the value of userdata.

How to show value dynamically in vue js wth div

showing values from url dynamically, already showing in table correctly, but i want show with div.
<vs-table ref="table" multiple v-model="selected" pagination :max-items="itemsPerPage" :data="products">
<template slot-scope="{data}">
<vs-tr :data="row" :key="index" v-for="(row, index) in data">
<vs-td>
<p>{{data[index].name}}</p>
</vs-td>
</vs-tr>
</template>
</vs-table>
now checking with this div
<template slot-scope="{data}">
<div v-for="(row1, index1) in data" v-bind:key="row1.id">
{{data[index1].name}}
</div>
</template>
this div code not working
If you are running these both on the same page it might have something to do with your :keys being on the same ID. e.g. set the keys with a prefix
<div v-for="(row, index) in data" v-bind:key="'div-'+row.id">
{{data[index].name}}
</div>

VueJS slot in v-for

I want to make a grid component which accepts as slot additional column cell.
<grid>
<td slot="additional-column">...</td>
</grid>
In the actual component:
<template>
<table>
<div v-for="item in items">
...
<slot name="additional-column"></slot>
</div>
</table>
</template>
Unfortunately the slot starts repeating itself and this is something vuejs doesn't like.
Duplicate presence of slot "additional-column" found in the same render tree - this will likely cause render errors.
Does anybody know how can I deal with this issue?
Thanks in advance!
This definitely seems to be your issue. You could do it this way too (as described here). See last paragraph before the subheading Destructuring.
Parent:
<grid>
<td :slot="['additional-column', item].join('-')" v-for="item in items">
...
</td>
</grid>
Child:
<table>
<div v-for="item in items">
...
<slot :name="['additional-column', item].join('-')"></slot>
</div>
</table>
PS: I have NOT tried this out. If you have difficulties I could create a fiddle and share.
Make the item a nested component (which you'll be repeating using v-for) and render the additional-column slot in that particular component.
That's the proper way to overcome this issue. The idea is that you need to have one single slot with a particular name per component.
That is, you could do it that way, which is a very rough version of it but nicely outlines the idea:
<!-- Grid Template -->
<template>
<table>
<GridItem :item="item" v-for="item in items">
<!-- Maybe even pass that column conditionally, based on the item data -->
<div slot="additional-column">
Content of column
</div>
</GridItem>
</table>
</template>
<!-- GridItem Template -->
<template>
<div>
<div>Column 1</div>
<div>Column 2</div>
<slot name="additional-column" />
</div>
</template>