Home > front end >  Call a function with customized datatable in Vuejs
Call a function with customized datatable in Vuejs

Time:11-24

I just started with Vuejs (Composition API) and trying to create my own kind of "datatable".

Managed to create the columns and the rows and all is great (event the call via ajax).

But now I have some kind of problem which I cant figure out how to fix.

I'm calling the Datatable component like this:

<DataTable :config="{
  data: {
    type: 'remote',
    url: '/api/categories/get'
  },
  columns: [
    {
      field: 'id',
      title: '#'
    },
    {
      field: 'name',
      title: 'Name'
    },
    {
      field: 'order',
      title: 'Placement'
    },
    {
      field: 'actions',
      title: 'Actions',
      template: 'SOME HTML & CALL FUNCTION'
    }
  ]
}" />

as you can see in the last column there is a new key called 'template'. the point is to create an "html" value, like buttons and stuff like that.

On the Datatable component I'm checking to see if there is "template" key, and if it's exists I want to display it

I did something like that:

<template v-if="column.template">{{ HTML }}</template>

I managed to show the buttons/everything else. the problem that I cant make the button to call any function.

Let's say I want to add delete button, something like that:

field: "actions",
title: "Actions",
template: () => "<button @click="delete(id)" >delete</button>"

How can I make it work? if I'm not using it's correctly, would love to hear & learn how to do it right.

Thanks in advance

CodePudding user response:

You can use scoped slots to render some templates that also have access to the state of the child component.

So you would define a slot in your table that have the name of the column <slot v-bind="item" :name="column.name" /> and the v-bind="item" would allow you to access the row data in the slot definition in the parent.

<template>
    <table>
        <thead>
            <tr>
                <th v-for="column in columns">{{column.title}}</th>
            </tr>
        </thead>
        <tbody>
            <tr v-for="item in items">
                <td v-for="column in columns">
                    <template v-if="column.name">{{item[column.name]}}</template>
                    <slot v-bind="item" :name="column.name"></slot>
                </td>
            </tr>
        </tbody>
    </table>
</template>


<script setup lang="ts">
defineProps<{
    items: any[],
    columns : {title? : string, name? : string}[]
}>()
</script>

<style>
th {
    font-weight: bold;
}
</style>

And then use it like this

<script setup lang="ts">
import { ref } from 'vue';
import MyTable from './components/MyTable.vue';

const items = ref([{msg : 'Hello' }, { msg: 'World' }]);

</script>

<template>
  <main>
    <MyTable :items="items" :columns="[{ title : 'Message', name: 'msg' }, { name: 'delete'}]">
      <template #delete="item">
        <button @click="items.splice(items.findIndex(x => x.msg === item.msg), 1)">Delete</button>
      </template>
    </MyTable>
  </main>
</template>
  • Related