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

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.

Related

How do I retrieve the value of my key button and row in v-for using 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

vuetify: why the table is sorted whenever the user clicks into the input field

I have a vuetify datatable, the original solution is dynamic allocation of search text field using v-for for each of the column and then multi filter is implemented. following is my solution:
<template v-for="(header, i) in columns" v-slot:[`header.${header.value}`]="{ }">
{{ header.text }}
<v-text-field :key="i"
v-model="multiSearch[header.value]"
class="pa"
type="text"
:placeholder="header.value"
prepend-inner-icon="mdi-magnify"
></v-text-field>
</template>
The problem is whenever an user clicks on the text field of a particular column, the sorting function also runs at the same time. I have a miniature solution on the following pen which has the same behaviour. I tried to put one div after template tag but still the same. Kindly have a look at it. Any help would be appreciated.
Code Pen
Wrap the text field with a DIV and attach an empty handler to prevent the bubbling of CLICK events:
<template v-for="(header, i) in columns" v-slot:[`header.${header.value}`]="{ }">
{{ header.text }}
<div #click.stop>
<v-text-field :key="i"
v-model="multiSearch[header.value]"
class="pa"
type="text"
:placeholder="header.value"
prepend-inner-icon="mdi-magnify"
></v-text-field>
</div>
</template>

Vuejs Rebind an Html Select List

I have a data-grid.
When the user clicks the "edit" button for a row in the grid, the div which contains the grid is made invisible (using v-if) and another div which contains an update form for that item is made visible (also using v-if).
As an added complication, the "edit" form contains a selectlist. This is bound to an array, but the array to which it is bound varies, depending on which item is selected in the grid (the items in the grid are different kinds of things).
How do I get that selectlist to rebind each time an item in the grid is clicked on for edit.
I realise I could do this by making a component, but that to me is overkill.
Is perhaps a slot the answer? Not sure how to proceed.
This is the relevant code:
<b-row v-if="editClaimFormVisible" class="mt-6 justify-content-md-center">
<b-col cols="6">
<b-form #submit.prevent="editClaimSubmit">
<b-form-group label="Enter New Claim Value:">
<b-form-select v-model="selectedClaimForEdit.claimValue" :options="getClaimOptions()" value-field="id" text-field="name" required>
<template #first>
<b-form-select-option :value="null" disabled>-- Please select a claim --</b-form-select-option>
</template>
</b-form-select>
</b-form-group>
<b-form-group>
<b-button type="submit" variant="primary">Save</b-button>
</b-form-group>
</b-form>
</b-col>
</b-row>

How do I get to open only one detail in b-table?

When the button is clicked, the row details are opened. When another row detail is opened, I want to ensure that the open details are closed. One line detail must remain open
sample screenshot
As you can see in the example, there is more than one line, while the detail in the first line is open, I want the detail in the second line closed.
<b-table
show-empty
small
stacked="md"
:items="items"
:fields="fields"
:current-page="currentPage"
:per-page="perPage"
:filter="filter"
:filter-included-fields="filterOn"
:sort-by.sync="sortBy"
:sort-desc.sync="sortDesc"
:sort-direction="sortDirection"
#filtered="onFiltered"
>
<template #cell(name)="row">
{{ row.value.first }} {{ row.value.last }}
</template>
<template #cell(actions)="row">
<b-button size="sm" #click="info(row.item, row.index, $event.target)" class="mr-1">
Info modal
</b-button>
<b-button size="sm" #click="row.toggleDetails">
{{ row.detailsShowing ? 'Hide' : 'Show' }} Details
</b-button>
</template>
<template #row-details="row">
<b-card>
<ul>
<li v-for="(value, key) in row.item" :key="key">{{ key }}: {{ value }}</li>
</ul>
</b-card>
</template>
</b-table>
I don't have the custom component code such as b-table, but what you would like to do is the following
https://vuetifyjs.com/en/components/data-tables/#expandable-rows
Basically a separate array tracking which rows are currently open.
Assuming b-table extends v-data-table, pass through the :expanded property and add the tracking array.
On details open, set the array to [], which should close everything.
And immediately afterwards, set the index of the row you want to open to 1.
See the above Vuetify link for an example of how they do it, make sure to toggle the "Single Expand" option.

VUEJS List items editable with button #click (button is in another component)

I need to make list items editable on click.
I have a template with a card displaying the list items, and a button component that contains, among others, a button that will trigger modify(). When this button is clicked the list items should become text inputs and a save button should appear at the bottom.
I read about contentEditable = true, but I don't know where to set it. If it's #click, the button component needs to be aware of the list items.
How to let the button know about those list items?
<button /> should be child of <detailActivity>... so Props?
Here's the template with the list items: <detailActivity />
<b-row>
<b-card
header-tag="header"
footer-tag="footer"
class="text-center"
>
<h3 slot="header" class="mb-0">Activity Details</h3>
<ul
v-for="value in currentActivity"
:key="value.id"
class="listValues">
<li>....</li>
<li>....</li>
<li>....</li>
</ul>
<div slot="footer">
<buttons />
</div>
</b-card>
</b-col>
<b-col xs="8">
<activity-map />
</b-col>
</b-row>
Inside the <button /> component, among others, the edit button:
<b-button
variant="warning"
#click="edit"
>
Any idea on how I should do this?
THANKS