Vuejs b-table array template - javascript

I want to create a b-table template can understand data type and if it is array then it shows array keys one under the other. For example:
data.item.value may be :
string
array
json
<b-table :items="mydata">
<template #cell(name)="data">
<b-list-group-item>
{{data.item.value}}
</b-list-group-item>
</template>
</b-table>
if data.item.value is array should open new b-list-group-item automatically:
first b-list-group-item : data.item.value[0].name
second b-list-group-item : data.item.value[1].name
How can I handle this?

You would use v-for on the array inside your template. Then you can use v-if to special case type inside the group-item.
<b-table :items="mydata">
<template #cell="data">
<b-list-group-item v-for='value of data.item.value'>
{{value.name}}
</b-list-group-item>
</template>
</b-table>

Related

Cannot dynamically pass a prop to a component within a v-for loop in Vue js

I have an array sheets initialised in data, has an item pushed to it when a button is pressed
data() {
return {
sheets: []
};
}
And in the html I'm trying to add a Card component for each element in this array and pass the data as a prop, but none of the components get rendered and there is no error message. I also tried putting the v-for directly on the component but it has the same result
<div id="sheets">
<template v-for="c in sheets">
<Card :info="c"/>
</template>
</div>
Meanwhile if I do something like this, it displays all the data in the array correctly, so I dont understand whats going wrong here
<div id="sheets">
<template v-for="c in sheets">
<span>{{c}}</span>
</template>
</div>
--
Solution
In my component the data from prop was being manipulated in the created() function, it works after I did this in the mounted() function instead
Make sure you have following things done correctly:
Imported your Card component
Passing and accessing the props
There are no conflicts in the variable names and id names
Next thing you need to know and is a must while using v-for is adding :key to the element which acts as unique id and lets Vue detect that each element is unique inside the v-for. One thing to be noted while using :key is that, you cannot use :key on the <template> tag.
Adding a validation using v-if would be a good idea, so v-for only executes if the array is not empty.
<div id="sheets">
<template v-if="sheets.length">
<Card v-for="(sheet,index) in sheets" :key="index" :info="sheet" />
</template>
</div>
Edit 1: As mentioned by Michal in the comments section that using index can lead to difficulties while debugging issues. You can use either :key="sheet" or if sheet is object including some unique id in it, then use :key="sheet.id" and get rid of the index
// use this if sheet is not an object
<div id="sheets">
<template v-if="sheets.length">
<Card v-for="sheet in sheets" :key="sheet" :info="sheet" />
</template>
</div>
OR
// use this if sheet is an object having some unique id in it
<div id="sheets">
<template v-if="sheets.length">
<Card v-for="sheet in sheets" :key="sheet.id" :info="sheet" />
</template>
</div>
As :key is not mandatory, It should work without that as well. I just created a working fiddle below. Please have a look and try to find out the root cause.
Vue.component('card', {
props: ['info'],
template: '<span>{{ info }}</span>',
});
var app = new Vue({
el: '#app',
data: {
sheets: [],
count: 0
},
methods: {
create() {
this.count++;
this.sheets.push('Sheet' + this.count);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button #click="create">Create a Card!</button>
<template v-for="c in sheets">
<Card :info="c"></Card>
</template>
</div>

what does {on, attrs} make in vue/vuetify?

I am aware that this question has been asked already but I still struggle to understand what does it mean?
<v-dialog
v-model="dialog"
width="500"
>
<template v-slot:activator="{ on, attrs }">
<v-btn
color="red lighten-2"
dark
v-bind="attrs"
v-on="on"
>
Click Me
</v-btn>
</template>
(that is taken from official vuetify documentation https://vuetifyjs.com/en/components/dialogs/#usage , but I suspect there is just a JS thing that I don't understand).
What does {on, attrs} mean and how they propagate down to v-btn where they are used in v-on and v-bind?
There a few concepts here that need to be explained.
"Scoped slots" (or just "slots" since Vue 3) can pass data to the parent component. Think of the slot as kind of like a function with arguments. In this case the activator slot of <v-dialog> is passing an object containing properties on and attrs for use inside the slot content template. You should refer to the <v-dialog> docs to know how this data should be used; in this case <v-dialog> needs to know when the activator is clicked in order to present the dialog, which is why it exposes on and attrs that you need to link to whatever custom button you designate to be the dialog activator.
In a lot of component libraries, it's common for slots to expose on (event listeners) and attrs (attributes/props) that the component requires you to set on a component in the template; for this you use v-on and v-bind respectively. Refer to the docs to see how these directives can be used in this way to bind multiple attributes at once:
<!-- binding an object of attributes -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
This specific syntax (object destructing):
<template v-slot:activator="{ on, attrs }">
<v-btn v-bind="attrs" v-on="on">
is the same as this:
<template v-slot:activator="scope">
<v-btn v-bind="scope.attrs" v-on="scope.on">
The on and attrs properties are just being extracted into separate variables.

Get date from slot in Vue

I got simplecomponent:
<template>
<v-chip>
<slot></slot>
</v-chip>
</template>
and I use it like that:
<formatted-date>2020-22-03</formatted-date>
how can I access the date given in the slot in the component?
If you need to manipulate the given data, use PROPS instead slots.
<template>
<v-chip>
{{ date }}
</v-chip>
</template>
<script>
...
props: ['date'],
...
</script>
And use it like that:
<formatted-date date="2020-22-03"></formatted-date>
This way you can access it using this.date inside the component.
Read more at: Official Docs - Props

get specific element of an table

hello every one I am trying to get a specific element in my table and add a class to it to make the red buttons green when an image is uploaded. But i can't get the specific row in my table. Any one a solution for this?
My code:
<b-table hover
:filter="filter"
id="my-table"
:bordered="bordered"
:fields="fields"
:items="items"
:per-page="perPage"
:current-page="currentPage"
responsive
striped
small>
<template v-slot:cell(actions)="row">
<b-button id="btnImage" size="sm" #click="info(row.item, $event.target)" class="addModal mr-2" ref="addModal">
<font-awesome-icon :icon="['fas', 'image' ]" />
</b-button>
</template>
</b-table>
If i do this: var tr = document.getElementById("my-table").getElementsByTagName("tr"); I get the following output:
inside every tr is an element thats called innerText that reference to the id that you can see here in my table:
But how do i get the specific row in my table and add an class to the button of that specific row?
Use scoped field slots
<template v-slot:cell(nameage)="data">
{{ data.item.name.first }} is {{ data.item.age }} years old
</template>
Refer https://bootstrap-vue.org/docs/components/table#scoped-field-slots. I think it's well documented.
For every one that needs it. I fixed the problem to give row.item as a parameter to my method very simple but is works great

Iterating slot content for iterated slots in child component in Vue.js

I've got a child component (that I cannot edit) where each row in an object is rendered inside a div with a specific slot, and I'd need to pass data from the parent for each of those elements. I'm trying to iterate through every element of the object in the parent component, generate a slot and pass the desired code to the child, but unfortunately I can't manage to and I can't find any material to support me.
The child component:
<div class="slotchildren" v-for="(child, childindex) in row.elementChildren" :key="childindex">
<span>element nr. {{child.id}}</span>
<slot :name="`element-child-${row[idlabel]}-${childindex}`" :row="child">
...
</slot>
</div>
The parent component (not working):
<template v-for="row in rows"> -->
<template v-slot:`element-row-${row.id}`="{row}">
//--> [vue/valid-v-slot] 'v-slot' directive doesn't support any modifier
//--> [vue/valid-v-slot] 'v-slot' directive must be owned by a custom element, but 'template' is not.
<span>{{row.name}}</span>
</template>
</template>
Is something like this feasible and how? If it's not, what could be a viable workaround, consideind that I can't edit the child component?
Thanks in advance.
I solved it with the following synthax:
<template v-for="row in rows" v-slot:[`element-row-${row.id}`]>
..
</template>

Categories

Resources