Reputation: 47
I'm trying to generate a dynamic b-table with editable fields and with two-way databinding.
I would like to not have any hardcoded values. Now, I have:
<b-table striped hover :items="filtered">
<template v-slot:cell(issueDescription)="row">
<b-form-input v-model="row.item.issueDescription" />
</template>
<template v-slot:cell(endTime)="row">
<b-form-input v-model="row.item.endTime" />
</template>
<template v-slot:cell(startTime)="row">
<b-form-input v-model="row.item.startTime" />
</template>
</b-table>
Where:
filtered = [ { "issueDescription": "this is a description", "endTime": "2020-02-11T14:00:00.000Z",
"startTime": "2020-02-11T01:24:00.000Z" }]
If I generate template with a v-for, then I got editable fields in every column, but no binding at each field.
<b-table striped hover :items="filtered">
<template v-for="x in filtered" v-slot:cell()="row">
<b-form-input v-model="row.item.BIND_TO_SPECIFIC_TABLE_ROW_COL" />
</template>
</b-table>
How do I bind to the specific row,col??
I've made a fiddle: https://jsfiddle.net/gfhu1owt/
Upvotes: 3
Views: 5306
Reputation: 10324
If you want to have ALL fields editable, you can use this syntax.
<template v-slot:cell()="{ item, field: { key } }">
<b-form-input v-model="item[key]" />
</template>
It's pretty similar to what you had. You just needed to use the key
from the slot context object. (I've shorthanded it a bit, but it's the same as going row.field.key
).
Also note that i don't use a v-for
in the template, this is because v-slot:cell()
is a fallback slot which is valid for all slots unless a specific one is defined. For example v-slot:cell(issueDescription)
would overwrite v-slot:cell()
for the issueDescription
field.
While the above works, the problem might come one day when you have a field you DONT want to be editable, like maybe an id
field in your object.
To solve this issue, I've defined my fields and passed them to the table. I've also added a editable
property to the fields i want to be editable. (note this is not a standard thing in the field object, but something specific for you use-case).
I then created a computed property editableFields
which returns all fields that have editable: true
, and then use editableFields
in my v-for
inside b-table
.
This way you can pick and choose which properties you want to be editable in your objects.
new Vue({
el: "#app",
computed: {
editableFields() {
return this.fields.filter(field => field.editable)
}
},
data: {
filtered: [
{
"id": "1",
"issueDescription": "this is a description",
"endTime": "2020-02-11T14:00:00.000Z",
"startTime": "2020-02-11T01:24:00.000Z"
},
{
"id": "2",
"issueDescription": "this is a description",
"endTime": "2020-02-11T14:00:00.000Z",
"startTime": "2020-02-11T01:24:00.000Z"
}
],
fields: [
{ key: 'id', label: 'ID' },
{ key: 'issueDescription', label: 'Issue Description', editable: true },
{ key: 'startTime', label: 'Start Time', editable: true },
{ key: 'endTime', label: 'End Time', editable: true }
]
}
})
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/[email protected]/dist/bootstrap-vue.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/[email protected]/dist/bootstrap-vue.min.js"></script>
<div id='app'>
<b-table :items="filtered" :fields="fields">
<template v-for="field in editableFields" v-slot:[`cell(${field.key})`]="{ item }">
<b-input v-model="item[field.key]"/>
</template>
</b-table>
</div>
Upvotes: 4