I would like to add an HTML data-xxxx
attribute to the HTML <table>
represented by a v-simple-table, but if I add a data attribute to the <v-simple-table>
it ends up in a wrapping div
two layers above the actual <table>
.
I use data attributes to target components in my test suite. In my POM I want to do:
get tableResultsAvailable () {
return $('table[data-qaid="results_available-panel"]');
}
In a page I might do this:
<v-skeleton-loader v-if="loading" type="table-tbody"
:types="{ 'table-tbody': 'table-row-divider@4', 'table-row': 'table-cell@3', }"/>
<v-simple-table v-else data-qaid="results_available-panel">
<thead>
Then in a test spec I might await the table while it loads:
await expect(MyAccountPage.tableResultsAvailable).toBeDisplayed()
However in the HTML the data is attached to a div
not a table
<div data-v-b386ddc8="" class="v-data-table v-data-table--fixed-height theme--light" data-qaid="results_available-panel">
<div class="v-data-table__wrapper" style="height: 395px;">
<table>
<thead data-v-b386ddc8="">
Therefore in my POM I have to unnecessarily broaden the selector to '[data-qaid="results_available-panel"]'
or rely on 'div[data-qaid="results_available-panel"]'
which is specific to the Vuetify structure which might change, neither of which are ideal.
I'm guessing I could use the default slot to override the whole table definition, but that seems overkill. I've noticed that css classes are also applied to the wrapper in this way.
Looking at the code, there is no way to programmatically access the <table>
element. You cannot override the table through the default slot, however, there is an undocumented wrapper
slot:
<v-simple-table>
<template #wrapper>
<div class="v-data-table__wrapper">
<table data-qaid="results_available-panel">
... (previous default slot content goes here)
<table>
</div>
</template>
</v-simple-table>
But you already said you are not comfortable with overriding the whole wrapper.
The remaining option is to set the attribute in pure JS, for example through a ref:
mounted(){
this.$refs.wrapper.$el.querySelector('table').dataset['quaid'] = 'results_available-panel'
}
But this is quite fragile since you are doing direct DOM manipulation on a node managed by Vue.
In both options, you rely on the internal structure of VSimpleTable, so you could just use the adjusted selector, which is probably easiest.
new Vue({
el: '#app',
vuetify: new Vuetify(),
mounted(){
this.$refs.wrapper.$el.querySelector('table').dataset['prop'] = 'asdf'
}
})
*[data-prop="asdf"]{
background: red;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-container>
Table with wrapper slot:
<v-simple-table>
<template #wrapper>
<div class="v-data-table__wrapper">
<table data-prop="asdf">
<tr><td>Table content</td><tr>
</table>
</div>
</template>
</v-simple-table>
Table with ref:
<v-simple-table ref="wrapper">
<template #default>
<tbody>
<tr><td>Table content</td><tr>
</tbody>
</template>
</v-simple-table>
</v-container>
</v-main>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>