Enhancing Vue 3 Tables with Dynamic Slots

I have a unique and specific inquiry regarding Vue3, slots, and the components I've developed for a reusable table setup.

CustomTable.vue

<template>
  <table>
    <thead>
      <slot renderAs="header"></slot>
    </thead>
    <tbody>
      <tr v-for="(row, index) of rows" :key="index">
        <slot renderAs="cell" :row="row"></slot>
      </tr>
    </tbody>
  </table>
</template>

<script setup lang="ts">
  const rows = [{
    name: "Row 1",
    col2: "XX",
    col3: "YY"
  },
  {
    name: "Row 2",
    col2: "XX",
    col3: "YY"
  },
  {
    name: "Row 3",
    col2: "XX",
    col3: "YY"
  }];
</script>

CustomTableColumn.vue

<template>
  <th v-if="props.renderAs === 'header'" class="p-2">
    <slot name="header" :header="props.header">
      {{ props.header }}
    </slot>
  </th>
  <td v-else-if="props.renderAs === 'cell'" class="p-2">
    <slot :value="props.property ? row[props.property] : row">
      {{ props.property ? row[props.property] : "" }}
    </slot>
  </td>
</template>

<script setup lang="ts">
  const props = defineProps<{
    renderAs?: string;
    header?: string;
    property?: string;
    row?: any;
  }>();
</script>

In this implementation, CustomTableColumn can be displayed in either header or cell format.

Implementation Example

<CustomTable v-slot="slotProps">
  <CustomTableColumn v-bind="slotProps" header="Column 1" property="name" v-slot="cellProps"&...

Inquiry: I notice that I am passing down slotProps from CustomTable to CustomTableColumn. Is there a way to eliminate this step and pass them implicitly?

Answer №1

Utilize a functional component within the table to automatically add slot props to the columns:

VUE SFC PLAYGROUND

<script setup>
  const rows = [{
    name: "Row 1",
    col2: "XX",
    col3: "YY"
  },
  {
    name: "Row 2",
    col2: "XX",
    col3: "YY"
  },
  {
    name: "Row 3",
    col2: "XX",
    col3: "YY"
  }];

import { useSlots } from 'vue';

const slots = useSlots();

const renderCols = props => {

  const cols = slots.default();
  cols.forEach(vnode => Object.assign(vnode.props ??= {}, props));
  return cols;

};
</script>


<template>
  <table>
    <thead>
      <render-cols renderAs="header"/>
    </thead>
    <tbody>
      <tr v-for="(row, index) of rows" :key="index">
        <render-cols renderAs="cell" :row="row"/>
      </tr>
    </tbody>
  </table>
</template>

The implementation:

<script setup>
import FSTable from './FSTable.vue';
import FSTableColumn from './FSTableColumn.vue';
import { ref } from 'vue'

const msg = ref('Hello World!')
</script>

<template>
<FSTable>
  <FSTableColumn header="Column 1" property="name" v-slot="cellProps">
    <!-- This column renders a custom cell -->
    CustomCell: {{ cellProps.value }}
  </FSTableColumn>
  <FSTableColumn header="Column 2" property="col2">
    <!-- This column renders the default cell -->
  </FSTableColumn>
  <FSTableColumn header="Column 3" property="col3">
    <!-- This column renders a custom header -->
    <template #header="headerProps">
      CustomHeader: {{ headerProps.header }}
    </template>
  </FSTableColumn>
</FSTable>
</template>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Components in need of updating

I'm currently using a template to show a list of components: <template> <v-container id="container"> <RaceItem v-for="(item, index) in items" :key="item + index" /> (...) Whenever I update the " ...

Tips for putting distance between the digits in a number

Is there a way in Vue to format an input field that displays "10000" as "10 000" when typed by the user? ...

Vue: auto-suggest feature in a text input field

I am looking to implement a text field with typeahead functionality. Essentially, I have a collection of words and as you start typing in the field, suggestions should appear based on the input. The challenge is that it should be capable of providing sugge ...

Utilizing Vue.js to share a single array of data across two distinct input lists

For a clearer understanding of my requirements, I have put together a demo on JSFiddle: https://jsfiddle.net/silentway/aro5kq7u/3/ The code snippet is presented below: <script src="https://cdn.jsdelivr.net/npm/vue"></script> <div id=" ...

The Vue directive v-for with an empty key attribute does not function properly

Looking for some assistance. In my App.vue file, I have the following code: <template> ... <select class="form-control"> <option v-for="{car, index} in cars" :key="index"> {{ car.name }} </option> </select> ...

Facing difficulty in passing data to a child component through VueX

<template> ... <note-info></note-info> <note-list></note-list> ... </template> I am utilizing VueX and store.js export default { state: { noteDataList: [], }, mutations: { setNoteDataList: fu ...

Issue of delayed loading of CSS in Vue.js application

My vue PWA is experiencing slow loading of CSS when using Vue Bootstrap and Buefy. I attempted to use V cloak, but it only hides components milliseconds after the raw HTML is briefly displayed without any CSS applied. I am looking for a method to display ...

Error: An unexpected symbol '<' was encountered after the build process in Vue.js

I just finished deploying a MEVN stack application to heroku. While everything is functioning properly locally, I am encountering a blank page and the following errors in the console post-deployment: Uncaught SyntaxError: Unexpected token '<' ...

Utilizing Vue.js to fetch information from a post API in Node.js

I'm currently working on developing a post API in Node.js, with Vue.js as my frontend framework and using vue-resource to interact with APIs. Here is the submit function I have implemented on the frontend: validateBeforeSubmit() { var self = this ...

How to display an HTML element conditionally with v-if based on a variable's value

Looking for a way to display a <div> element, including nested <div>s, based on the value of a variable. I'm currently using v-if, but open to better suggestions. I attempted wrapping the entire <div> in a <template v-if> as s ...

Issue: Unable to locate the module 'babel-code-frame' in VUEJS (ESLINT)

Here are the current versions: -npm: 6.14.4 -node: v10.19.0 -eslint: v5.0.1 -linux: ubuntu 20.04 This is my script: vue create vue1 cd vue1 npm run serve This is my package.json: { "name": "vue1", "version": "0. ...

When setting up Vue.js for unit testing, the default installation may show a message stating that

Recently set up a fresh Vue project on Windows 7 using the VueJS UI utility. Unit testing with Jest enabled and added babel to the mix. However, when running "npm test" in the command line, an error is returned stating 'Error: no test specified' ...

Issue: Elements within an iteration must include a 'v-bind:key' directive. Vue/Require-v-for-key error detected

As someone who is just starting to learn Vue, I recently attempted to create a commercial product page by following a tutorial. However, upon trying to run 'npm run serve', I encountered an error that read: Error: Elements in iteration expect to ...

Launching a Component Using the Menu Feature in VueJS 3

I'm not particularly versed in frontend development, but I'm facing a bit of a challenge. I have a menu with an option labeled "VIEW PROFILE," and I want it to open another vue file I created with user information when clicked. The slide-out func ...

Unexpected token encountered when testing Ajax call with JSON response

Currently, I have a Vue application with the following code snippet... var vm = new Vue({ el: '#Workbooks', components: { 'workbook-list': workbooklist }, data: { workbooks: [], message: '', loading: true, ...

Can we utilize v-bind:value or v-model for the data object retrieved from the network?

I am trying to make VueApp use either v-model or v-bind:value for the object received from the network API. For instance, if the Vue app fetches an object from the API in this format: { field1:value1, field2:value2, ......... , field100:value100 } ...

What is the method for incorporating a global function with a plugin to display notifications in Vue.js?

Recently, I encountered an issue while trying to create a global function using a plugin. Everything seemed to be working fine until I faced difficulties in displaying my notifications. Tired of repeating the notification display methods everywhere in my c ...

Vue template component encounters a break in functionality due to the presence of

Having trouble adding a href link with a variable in my vue template. It seems to be breaking and I can't figure out why. The issue specifically lies with the "/post/update" href, as it is trying to reference it as a variable instead of a link. Howeve ...

Error: Attempting to access the `isPaused` property of a null object is not possible

For my Vue front-end app, I'm attempting to integrate wavesurfer.js. However, upon receiving the audio file link from the backend, I encounter the following error: wavesurfer.js?8896:5179 Uncaught (in promise) TypeError: Cannot read property 'isP ...

Vuex: updating the state, but the computed property remains unchanged

I am currently working on a component that retrieves data from the 'endpoints' property in the store, makes some adjustments to it... computed: { ...mapState(['endpoints']), adjustedEndpoints () { ...