I am trying to use the bootstrapVue table found here
If i use their example exactly the table works great.
<b-table striped hover :items="items"></b-table>
However once i use
<b-table striped hover :fundingInstructions="fundingInstructions"></b-table>
My table does not display and when i look in the dev tools i see that my table has [object,Object] for each object i return from my api.
If i console log my data i see an array [] with multiple objects. How do i get the table to display my data?
const items = [
{ isActive: true, date:'10/20/2018', amount:'$4568.00', city:'FL Palm Beach' },
{ isActive: false, date:'10/21/2018', amount:'$789.23', city:'FL Daytona Beach' },
{ isActive: false, date:'10/21/2018', amount:'$999.99', city:'FL Key West' },
{ isActive: true, date:'10/22/2018', amount:'$589.00', city:'FL Deltona' }
]
export default {
data() {
return {
fundingInstructions : [],
fields: [ 'subMerchantName', 'fundsTransferId', 'amount' ,'accType', 'submitDate' ],
items: items
}
},
methods:{
async GetFundingInstructionInfo(){
this.fundingInstructions = await api.getAllFundingInstructions()
}
Ok, so i figured out what the problem was and hence the solution.
In the table html it should look like this
<b-table striped hover :items="fundingInstructions"></b-table>
It seems that items is a key term and your collection goes in the quotation. That's it!
Related
I have two v-data-tables that are being rendered in a component. The first one is imported from another file as the matching-game-crud-table. This is the answer table. This first table manipulates information for the answerObject array, which is also used in the second tables to populate the v-select dropdown element. The first table (answer table) is set up like this below. Its items are updating the answerObjects on the main file.
<template>
<v-container>
<v-data-table
:headers="tableHeaders"
:items="items"
class="elevation-1"
>
<template #[`item.display`]="{item}">
<v-text-field
v-model="item.display"
:hide-details="true"
dense
outlined
:autofocus="true"
label="Display"
>
<!-- <v-icon v-if="header.draggable" slot="prepend"
>mdi-drag-vertical</v-icon
> -->
</v-text-field>
</template>
</v-data-table>
</v-container>
</template>
<script>
import draggable from 'vuedraggable'
import _ from 'lodash'
export default {
components: { draggable },
props: {
headers: { type: Array, required: true, default: [] },
defaultItem: { type: Object, required: true, default: {} },
allowDrag: { type: Boolean, required: false, default: false },
useModal: { type: Boolean, required: false, default: false },
data: { type: Array, required: true, default: [] },
},
data: () => ({
dialog: false,
dialogDelete: false,
items: [],
editedIndex: -1,
editedItem: {},
}),
computed: {
tableHeaders() {
let new_headers = JSON.parse(JSON.stringify(this.headers))
new_headers.push({
text: 'Actions',
value: 'actions',
sortable: false,
})
return new_headers
},
},
mounted() {
this.items = _.cloneDeep(this.data)
this.editedItem = _.cloneDeep(this.defaultItem)
},
created() {},
methods: {
addNew() {
console.log('add new')
const addObj = _.cloneDeep(this.defaultItem)
addObj.id = this.items.length + 1
this.items.push(addObj)
this.$emit('input', this.items)
},
},
}
The main page is set up like this. This is the page where you can see the second v-data-table with the v-select that is using the answerObjects array. The matching-game-crud-table is the file that utilizes the first table. There is a watch set up for the answerObject on the main file so that it is updated with the newest empty answer object from the matching-game-crud-table component.
<matching-game-crud-table
:headers="headers"
:default-item="default_item"
:data="answerObjects"
allow-drag
v-model="answerObjects"
></matching-game-crud-table>
<v-data-table
:headers="promptHeaders"
:items="prompts"
class="elevation-1"
>
<template #[`item.answer`]="{item, index}">
<v-select
:hide-details="true"
v-model="item.answer"
:items="answerObjects"
item-text="display"
item-value="display"
outlined
dense
label="Choose an answer value"
#input="change($event, true)"
></v-select>
</template>
</v-data-table>
<script>
import draggable from 'vuedraggable'
import _ from 'lodash'
import MatchingGameCrudTable from '../../MatchingGameCrudTable.vue'
export default {
name: 'MatchingGame',
components: { MatchingGameCrudTable, draggable },
props: {
value: { type: String, required: true },
data: { type: Object, required: true },
},
watch: {
answerObjects(newData, oldData) {
console.log(newData)
this.items = [newData]
console.log(this.items)
// this.mainBucket = this.setMainBucket()
},
},
data(){
return{
default_item: {
id: 0,
display: '',
feedback: '',
},
prompts: [],
answerObjects: [],
items: [],
}
}
</script>
The issue that seems to be happening is that if I add a new Answer to the answer table, then the addNew function is called and updates the answerObjects array with an empty answer object. For some reason if I also have an empty prompt object on the second table that has not been filled in yet, so the prompt.answer key is "". Then the v-select will take on the empty answer objects as the prompts answer. So as I fill in an answer in the empty answer object. The prompt answer is linked and is updated along with it. But the prompt answer is still "", it is just updating the v-select dropdown. I want the v-select to remain unchosen. And then the dropdown should populate with the answer value, but the user should be manually selecting it. I am unsure of why this link is occuring
I would suggest u fetch data from a central state like vuex, if the v-select is triggered on the first table it alters the state, then the second table uses the altered state
I am trying to create a table where the data can be edited directly in the cells. However, I don't understand how to do this.
I am using Vue.js, Vuexy and vue-good-table 2.21.1. The data is contained in the mediaPlanData variable and is reactive. The table is successfully populating with data and can be modified. However, when I change the data in the cells, this variable does not change. I did not find in the documentation vue-good-table how to do this. Please tell me how can I achieve the desired result?
<vue-good-table
:columns="columns"
:rows="mediaPlanData"
:select-options="{
enabled: true,
selectOnCheckboxOnly: true, // only select when checkbox is clicked instead of the row
selectionInfoClass: 'custom-class',
selectionText: 'rows selected',
clearSelectionText: 'clear',
disableSelectInfo: true, // disable the select info panel on top
selectAllByGroup: true, // when used in combination with a grouped table, add a checkbox in the header row to check/uncheck the entire group
}"
#on-selected-rows-change="onRowClick"
>
<template slot="table-row" slot-scope="props">
<span>
<b-form-input v-model="props.row[props.column.field]"
type="text"
></b-form-input>
</span>
</template>
</vue-good-table>
data() {
return {
pageLength: 10,
columns: [
{
label: 'Channel Code',
field: 'channelCode',
},
{
label: 'Product',
field: 'product',
}
],
mediaPlanData: [] //[ {"channelCode": "P230", "product": "Test"}, {"channelCode": "P230", "product": "Test4"}, {"channelCode": "P230", "product": "Test45"}, {"channelCode": "Р230", "product": "Test2"}]
}
}
methods: {
onRowClick(params) {
console.log('onRowClick' + JSON.stringify(params))
this.$toast({
component: ToastificationContent,
props: {
title: `Hello user! You have clicked on row ${params.selectedRows.product}`,
icon: 'UserIcon',
variant: 'success',
},
})
}
}
I have solved this problem.
Added to b-form-input
#change="changeCell(props.row[props.column.field], props.column.field, props.row.originalIndex)"
And adden method
changeCell(changedData, column, row) {
this.mediaPlanData[row][column] = changedData
},
I need a dropdown that supports tagging and can be styled easily, so I decided to implement vue-multiselect. It works but the problem is that I have a predefined tag in my dropdown when the page loads and I don't what that, how can I remove it? Here is how it looks now:
and here is how I want it to look:
Here is my html code:
<div>
<multiselect v-model="value" tag-placeholder="Add this as new tag" placeholder="Assesors" label="name" track-by="code" :options="options" :multiple="true" :taggable="true" #tag="addTag"></multiselect>
</div>
and here is my js:
data () {
return {
showAddUserDialog: false,
value: [
{ name: 'Assesors', code: 'as' }
],
options: [
{ name: 'Assesors', code: 'as' },
{ name: 'Finance', code: 'fi' },
{ name: 'Sales', code: 'sa' }
]
}
},
methods: {
addTag (newTag) {
const tag = {
name: newTag,
code: newTag.substring(0, 2) + Math.floor((Math.random() * 10000000))
}
this.options.push(tag)
this.value.push(tag)
}
}
Well, by the <multiselect> configuration you used and the expected behavior your showed...
You have this https://imgur.com/a/D9nEKfD to become this https://imgur.com/a/baTYXht
I looks like you want to load your page only showing the placeholder, but if you'd like to only show your placeholder, you shouldn't have a value in the value variable, as you have:
data () {
return {
showAddUserDialog: false,
value: [
{ name: 'Assesors', code: 'as' } // <- remove this
],
options: [
{ name: 'Assesors', code: 'as' },
{ name: 'Finance', code: 'fi' },
{ name: 'Sales', code: 'sa' }
]
}
}
Because the behavior of the component is show your current tags, right?
So if this tag is the placeholder, you can add it to the value when the user submits the form without choosing any other tag.
But if you want to have it there as the value and trickery the component to only show it as a placeholder, I suggest you to deep dive in the docs about custom templating...
Here talks about it https://vue-multiselect.js.org/#sub-custom-option-template
And here talks about the tags slots
https://vue-multiselect.js.org/#sub-slots
Here is an example:
I have an array of objects (users) gotten by an api request. Its structure is something like this:
api response: (5) [{…}, {…}, {…}, {…}, {…}]
Inside this array, the objects are like this:
0: {
user_address_string: ('Street 1')
id: (3)
avatar: (img')
...
user: {
id: 1
first_name: 'Lucas'
last_name: 'Smith'
}
},
1: {...},
2: {...},
....
]
It is just a sample just to show you the structure.
As you can see, among its properties there's another object named user{}.
I need to display only the properties contained in this object.
I would like to keep the structure of the table I was using before I got this new api (which didn't have objects as properties).
<b-table
responsive
v-if="users && users.length > 0"
:fields="fields"
:items="users"
>
The template should be something like this:
<template slot-scope="data">
{{ data.item.user }}
</template>
data.item should be the single user in the users array of objects, and with .user I should be able to access the properties of its object property user. (Going further data.item.user.first_name, etc, to access the single properties in it). What am I missing?
Nothing is rendered on the screen.
No errors in the console though.
In the script I have:
users: [],
fields: [
{ key: 'id', label: 'ID'},
{ key: 'name', label: 'Name' }
]
So, how should I write the template for displaying the nested object’s properties?
Also, the directive v-if="users && users.length > 0" in the b-table should still work, right? It is still an array, but of objects this time. Please correct me if I am wrong.
Thank you
You can specify nested field keys in dotted notation:
export default {
data() {
return {
users: [],
fields: [
{ key: 'id', label: 'ID'},
{ key: 'user.first_name', label: 'First Name' },
{ key: 'user.last_name', label: 'Last Name' }
]
}
}
As #Troy Morehouse suggested, I just needed to redefine the fields definition as
{ key: 'user.first_name', label: 'First name' }
**UPDATE after #artworkjpm comment:
The HTML code should be something like this:
<b-table
v-if="users && users.length > 0 && !isLoading"
id="table-transition-userList"
:key="users.id"
responsive
:tbody-tr-class="userStatus"
:tbody-transition-props="transProps"
:fields="fields"
:items="users"
>
<template
v-slot:cell(fullName)="data"
>
{{ data.item.user.first_name }} {{ data.item.user.last_name }}
</template>
<template
v-slot:cell(buttons)="data"
>
<b-button
v-b-tooltip.hover
title="See plan"
class="btn-plan p2"
variant="primary"
:disabled="!data.item.user.is_active"
#click.prevent="seePlan(data.item), selectUser(data.item)"
>
<span class="svg-container">
<svg-icon icon-class="route" />
</span>
</b-button>
</template>
</b-table>
**Minor change in fields, but the concept is the same:
fields: [
{ key: 'fullName', label: 'User' },
{ key: 'buttons', label: 'Operations' }
],
Hope it helps.
xx
Whereever you get your data, you can extract the property you want and save locally in this case it would look something like this:
data()
return {
users: []
}
methods: {
async getUsersFromApi(){
const { data: {users }} = await axios.get(...)
users.map(user => {
this.users.push(user.user)
}
An easy way to do it is by using a formatter in fields definition:
data() {
return {
fields: [
{
key: "avg_score",
label: this.$t("avgScore"),
sortable: true,
sortByFormatted: true,
formatter: (value, key, item) => item.stats.avg_score?.text
},
],
items: [...your item list]
}
}
And in the template:
<b-table :items="items" :fields="fields"></b-table>
The formatter will print the specified key or value automatically.
I use bootstrap-vue. I took an example from the documentation - https://bootstrap-vue.js.org/docs/components/table/#table-body-transition-support.
Everything works well. But if I replace the data in th cells with my data, the effect stops working. Why it happens? How do i fix this?
<template>
<div class="container">
<div class="row">
<div class="col-sm-12 chartjs">
<b-table
id="table-transition-example"
:items="itemsForTable"
:fields="fieldsForTable"
striped
small
primary-key="a"
:tbody-transition-props="transProps"
></b-table>
</div>
</div>
</div>
<script>
export default {
data: function () {
return {
fieldsForTable: [
{ key: 'a1', sortable: true },
{ key: 'b', sortable: true },
],
itemsForTable: [
{ a1: 2, b: 'Two'},
{ a1: 1, b: 'Three'}
],
transProps: {
name: 'flip-list'
}
};
},
computed: {
},
mounted() {
},
methods: {
}
}
You also need to update primary-key to be a2. Without that it won't know which rows in the updated table are equivalent to the rows in the original table, so it can't perform the transition.
The value of that field is used to generate the Vue key for each row. It isn't exactly the same as the underlying Vue key, the table adds a prefix and suffix, but for most practical purposes you can think of them as being the same thing.
in my case i forgot to put id="table-transition-example" and its work now like a charm.