Giter VIP home page Giter VIP logo

linmasahiro / vue3-table-lite Goto Github PK

View Code? Open in Web Editor NEW
247.0 7.0 74.0 2.16 MB

A simple and lightweight data table component for Vue.js 3. Features sorting, paging, row check, dynamic data rendering, supported TypeScript, and more.

Home Page: https://vue3-lite-table.vercel.app/

License: MIT License

JavaScript 0.55% HTML 32.16% Vue 66.42% TypeScript 0.87%
table pagination typescript vue vue3 vuejs3 vuejs

vue3-table-lite's Introduction

vue3-table-lite

Lincense NPM GitHub release (latest by date) Website npm

GitHub Repo stars GitHub forks

SampleGif

A simple and lightweight data table component for Vue.js 3. Features sorting, paging, row check, dynamic data rendering, supported TypeScript, and more.

Document and demo

Document

Online Demo

Support

  • Row check event Support
  • Custom data display Support
  • Pagging Support
  • Sorting Support
  • Custom message Support
  • V-slot Support
  • TypeScript Support
  • Grouping Support

SampleCode

import

import VueTableLite from "vue3-table-lite";
import VueTableLite from "vue3-table-lite/ts"; // TypeScript

QuickStart

component

<VueTableLite
:is-loading="table.isLoading"
:columns="table.columns"
:rows="table.rows"
:total="table.totalRecordCount"
:sortable="table.sortable"
:messages="table.messages"
@do-search="doSearch"
@is-finished="table.isLoading = false"
/>

data

const table = reactive({
  isLoading: false,
  columns: [
    {
      label: "ID",
      field: "id",
      width: "3%",
      sortable: true,
      isKey: true,
    },
    {
      label: "Name",
      field: "name",
      width: "10%",
      sortable: true,
    },
    {
      label: "Email",
      field: "email",
      width: "15%",
      sortable: true,
    },
  ],
  rows: [],
  totalRecordCount: 0,
  sortable: {
    order: "id",
    sort: "asc",
  },
});

Event

const doSearch = (offset, limit, order, sort) => {
  table.isLoading = true;

  // Start use axios to get data from Server
  let url = 'https://www.example.com/api/some_endpoint?offset=' + offset + '&limit=' + limit + '&order=' + order + '&sort=' + sort;
  axios.get(url)
  .then((response) => {
    // Point: your response is like it on this example.
    //   {
    //   rows: [{
    //     id: 1,
    //     name: 'jack',
    //     email: '[email protected]'
    //   },{
    //     id: 2,
    //     name: 'rose',
    //     email: '[email protected]'
    //   }],
    //   count: 2,
    //   ...something
    // }
    
    // refresh table rows
    table.rows = response.rows;
    table.totalRecordCount = response.count;
    table.sortable.order = order;
    table.sortable.sort = sort;
  });
  // End use axios to get data from Server
};

More...

Go to Check!!

release

ver 1.4.0 : Added checkbox indeterminate state.
ver 1.3.9 : Added Vertical highlight option. `#93`
ver 1.3.8 : Allow HTML in header's label `#91`.
ver 1.3.7 : Fixed `#85`.
ver 1.3.6 : Fixed `#81`.
ver 1.3.5 : Fixed `#79`.
ver 1.3.4 : Fixed `#78`.
ver 1.3.3 : Fixed `#77`.
ver 1.3.2 : Fixed `#75`.
ver 1.3.1 : Fixed `#73`.
ver 1.3.0 : Fixed `#69`.
ver 1.2.9 : Added keep collapsed status option.
ver 1.2.8 : Added grouping collapse features. `#67`
ver 1.2.7 : Fixed `#63`.
ver 1.2.6 : Fixed `#61`.
ver 1.2.5 : Added table max-height prop and `#59` bugs.
ver 1.2.4 : Added grouping features. `#53`
ver 1.2.3 : Added option for fixed first column on horizontal scrolling.
ver 1.2.2 : Fixed result of sorting number as string was wrong on "static-mode" `#47`
ver 1.2.1 : Fixed "setting.pageSize" property is not accessible from outside and is not in sync with the "props.pageSize" property
ver 1.2.0 : Added Row click event `#41`
ver 1.1.9 : New Features `#35` `#36`
ver 1.1.8-1 : Removed unnecessary style-class and changed something class-name `#33`
ver 1.1.8 : Add option to set header/column class and style(in-line) `#32`
ver 1.1.7 : Add option to set custom values in page size dropdown `#29`
ver 1.1.6 : fixed bug. `#28`
ver 1.1.5 : Added classes to element for easier Styling. `#25`
ver 1.1.3 : fixed cannot get localTabel refs bugs.
ver 1.1.2 : changed import file on TypeScript.
ver 1.1.1 : added hide-paging and page number attribute and fixed `#23`.
ver 1.1.0 : remove Vue Dependency at bundle
ver 1.0.9 : column v-slot is not to be required on v-slot mode
ver 1.0.8 : fixed can't rendering customized display data on static mode bus.
ver 1.0.7 : support v-slot.
ver 1.0.6 : support static mode.
ver 1.0.5 : fixed Safari loading-mask is not overlapping the table.
ver 1.0.4 : support TypeScript.

vue3-table-lite's People

Contributors

gainskills avatar grafxflow avatar klemens189 avatar linmasahiro avatar roelofsaj avatar roman1510 avatar wattsie avatar yashwp avatar yoanhg421 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue3-table-lite's Issues

How to deal with asyncronous data?

Hi, based on the example in https://github.com/linmasahiro/vue3-table-lite/blob/master/src/examples/Filter.vue, how can I deal with a data that come from axios or database fetch? The computed function in the row field doesn't accept async/await function.

For example if I move the data initialisation to a test function.

const test = () => {
  for (let i = 0; i < 126; i++) {
    data.push({
      id: i,
      name: "TEST" + i,
      email: "test" + i + "@example.com",
    });
  }
}

Defining the table rows as below, will not show the data:

rows: computed(async () => {
    const ret = await setTimeout(test, 3000);
    return data.filter(
      (x) =>
        x.email.toLowerCase().includes(searchTerm.value.toLowerCase()) ||
        x.name.toLowerCase().includes(searchTerm.value.toLowerCase())
    );
  }),

However, removing the async/await keywords can show the data.

Better Semnatics for easier Styling

I love the simplicity of this table component.

I'd just wish for better HTML semantics for easier styling.

Take the pagination for instance.
Every item has the same classes and I can't easily distinguish them from being a previous/next page or a number button.
I also don't know which item symbolizes the currently selected page. A selected class would be helpful.

Binding prop data to datatable actions

I am currently having difficulties in binding my data which is to be used as a prop of my reusable component.

I want to have my datatable to have actions column, which contains buttons that will show its respective modal when clicked. I want my modal to be a separate component, which I can also bind the id of the row data.

Is there a way to achieve this?

is-slot-mode

I'm looking to only use one of columns with a v-slot to use a component,
But it seems that when you turn is-slot-mode to true that you have to make every column a v-slot

Is there a way I could add a v-slot without having to do them all?

I know display: exists but that doesn't fit my use case as I need to use vue components.

An optional slot mode would be ideal i.e default to not using a slot unless specified <3

Page Size prop isn't working?

I have the following in place:

<vue-table-lite
  :is-loading="table.isLoading"
  :is-slot-mode="true"
  :columns="table.columns"
  :rows="table.rows"
  :total="table.totalRecordCount"
  :sortable="table.sortable"
  :messages="table.messages"
  :page-size="2"
  @do-search="checkSearch"
  @is-finished="busy = false"
>

But it is still showing 10 results per page, not 2. Should I be doing this another way?

Add types to TS

I currently work Vue table lite in TS and present error as it doesn't have types

@is-finished looks like not triggering.

Hi,
I try to integrate your code. It's really a good job.
But I am facing some issues.
it's loading infinitely. tableLoadingFinish is not emitting?

here is my code

<template>
  <vue-table-lite
    :is-static-mode='false'
    :has-checkbox='true'
    :is-loading='table.isLoading'
    :is-re-search='table.isReSearch'
    :columns='table.columns'
    :rows='table.rows'
    :total='table.totalRecordCount'
    :sortable='table.sortable'
    :messages='table.messages'
    @do-search="doSearch"
    @is-finished='tableLoadingFinish'
    @return-checked-row='updateCheckedRows'
  />
</template>

<script lang="ts">
import { reactive } from 'vue';
import VueTableLite from 'vue3-table-lite';

export default {
  name: 'AccountsTab',
  components: {
    VueTableLite,
  },
  setup() : unknown {
    const sampleData1 = function (offst, limit) {
      let sampleoffst = offst;
      sampleoffst += 1;
      type Data = {
        id: number
        name: string
        email: string
      }
      const data: Data[] = [];
      for (let i = sampleoffst; i <= limit; i += 1) {
        data.push({
          id: i,
          name: `TEST${i}`,
          email: `test${i}@example.com`,
        });
      }
      return data;
    };

    const table = reactive({
      isLoading: false,
      isReSearch: false,
      columns: [
        {
          label: 'ID',
          field: 'id',
          width: '3%',
          sortable: true,
          isKey: true,
        },
        {
          label: 'Name',
          field: 'name',
          width: '10%',
          sortable: true,
          display: function display(row) {
            return (
              `<a href="#" data-id="${row.id}" class="name-btn">${row.name}</button>`
            );
          },
        },
        {
          label: 'Email',
          field: 'email',
          width: '15%',
          sortable: true,
        },
        {
          label: '',
          field: 'quick',
          width: '10%',
          display: function display(row) {
            return (
              `<button type="button" data-id="${row.id}" class="quick-btn">Button</button>`
            );
          },
        },
      ],
      rows: sampleData1(0, 20),
      totalRecordCount: 20,
      sortable: {
        order: 'id',
        sort: 'asc',
      },
      messages: {
        pagingInfo: 'Showing {0}-{1} of {2}',
        pageSizeChangeLabel: 'Row count:',
        gotoPageLabel: 'Go to page:',
        noDataAvailable: 'No data',
      },
    });

    const doSearch = (offset, limit, order, sort) => {
      table.isLoading = true;
      table.isReSearch = offset === undefined;
      // do your search event to get newRows and new Total
      table.rows = sampleData1(0, 10); // newRows
      table.totalRecordCount = 10; // newTotal
      table.sortable.order = order;
      table.sortable.sort = sort;
    };

    const tableLoadingFinish = function loadingFinish(elements) {
      table.isLoading = false;
      Array.prototype.forEach.call(elements, function load(element) {
        if (element.classList.contains('name-btn')) {
          element.addEventListener('click', function click(this:any) {
            // do your click event
            console.log(`${this.dataset.id} name-btn click!!`);
          });
        }
        if (element.classList.contains('quick-btn')) {
          // do your click event
          element.addEventListener('click', function click(this:any) {
            console.log(`${this.dataset.id} quick-btn click!!`);
          });
        }
      });
    };

    const updateCheckedRows = (rowsKey) => {
      // do your checkbox click event
      console.log(rowsKey);
    };

    // your first loading
    doSearch(0, 10, 'id', 'asc');

    return (
      {
        table,
        doSearch,
        tableLoadingFinish,
        updateCheckedRows,
      });
  }
};
</script>

Best regards,

Safari loader not overlapping the table

In Safari the 'loader' only appears as a bar at the top - not 100% width and height of table.

I have pushed a fix but it has only been tested in Safari, Chrome, Firefox on a macOS Big Sur.

#8

Looking for contributors?

We're considering adopting this table into our platform. I am wondering if you are looking for contributors? Also, it looks like you have duplicated the VueTableLite for typescript. Wondering if we should look at another way of handling that so we don't have to duplicate the code.

Anyways DM me. Would love to chat about this project and where you see it going.

Tutorial as video

Hi linmasahiro, maybe you can create a video that helpful everyone for use vue3-table-lite.

Backend data changes, but table does not react to data change

Hi,
Have an issue trying to implement a search function (on various fields) and have the table automatically reduce to that searched list.

Using Vue3 sfc component (and ts).

My setup is

const searchTerm = ref('')

linked to an input

<input v-model="searchTerm" />

Setup data and add some random entries

// Setup Reactive data
const data = reactive([])
// Load Random data
for (let i = 0; i < 126; i++) {
    data.push({
        id: i,
        email: faker.internet.email(), // Using Faker.js
        name: faker.name.findName(),
        address: faker.address.streetAddress(),
    })
}

created a computed value

const searchedData = computed(() => {
    return data.filter(
        x => 
            x.email.toLowerCase().includes(searchTerm.value.toLowerCase()) || 
            x.name.toLowerCase().includes(searchTerm.value.toLowerCase())
    )
})

Then return this from the setup()

return {
    searchTerm,searchedData,
}

And back in the template I watch the data

<p>
    Data: {{searchedData}}
 </p>

So, when I enter say "hotm" (or any search), the displayed data gets filtered as expected.

Yet the table does not update.

However, the table does update (reduced to the searched value list) when I change page or sort the columns (i.e. when the table components emits a do-search)

I actually was able to get it working (feels like a cludge) by using a watch then update "table.rows", as order and sort pageSize values are exposed so I was able to reslice from 0 to pageSize.
But as I said, feels a little hackish...

watch(searchedData, () => {
    table.rows = searchedData.value
        .sort(dynamicSort(table.sortable.order, table.sortable.sort))
        .slice(0, table.pageSize)
    table.totalRecordCount = searchedData.value.length
})

Any suggestions or workarounds?

!!! Feature Request !!!
Would be good to include a search function as part of the component.
Much like how you implement the sort function but have the search field emit an event.

PS: Would it make more sense to have the table sorting emit a do-sort event, and the a new search field emit a do-search event.

Many thanks in advance.

Cheers.

PS: for reference my dynamicSort is

const dynamicSort = (property, order) => {
    let sort_order = 1
    if (order === "desc") { sort_order = -1 }
    return function (a, b){
        if (a[property] < b[property]) {
            return -1 * sort_order
        } else if (a[property] > b[property]) {
            return sort_order
        } else {
            return 0
        }
    }
}

lost event click after dosearch

Hi,
I have a question about the event click on a button.
When I display the table all buttons are working well. But when I change de order of the tab with dosearch, I loose the click event of the button.
Do you know why?

I see:
@do-search='doSearch'
@is-finished='tableLoadingFinish'

But how doSearch trigger tableLoadingFinish to re inject the click behaviour?

Also in line 116 you have table.isLoading = true; but inside the same function I don't see table.isLoading = false;
I have to add it at the end or the tab change but the loading is still present.
https://github.com/linmasahiro/vue3-table-lite/blob/master/src/examples/CustomizeStyle.vue

Best regards,
Mehdi

Before
2022-01-31 at 21 29

After
2022-01-31 at 21 28

My code:

<template>
  <div class="contentAccountsTab">
    <vue-table-lite
      :is-static-mode='false'
      :has-checkbox='true'
      :is-loading='table.isLoading'
      :is-re-search='table.isReSearch'
      :columns='table.columns'
      :rows='table.rows'
      :total='table.totalRecordCount'
      :sortable='table.sortable'
      :messages='table.messages'
      @do-search='doSearch'
      @is-finished='tableLoadingFinish'
      @return-checked-rows='updateCheckedRows'
    />
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive } from 'vue';
import VueTableLite from 'vue3-table-lite';
import { useAuth } from '@/composable/auth';

// Define row data interface
interface rowData {
  id?: number;
  name: string;
  email: string;
  role?: string;
}

export default defineComponent({
  name: 'AccountsTab',
  components: { VueTableLite },
  setup() {
    const {
      listUsers,
    } = useAuth();

    const table = reactive({
      isLoading: false,
      isReSearch: false,
      columns: [
        {
          label: 'ID',
          field: 'id',
          width: '3%',
          sortable: true,
          isKey: true,
        },
        {
          label: 'Email',
          field: 'email',
          width: '15%',
          sortable: true,
        },
        {
          label: 'Role',
          field: 'role',
          width: '10%',
          sortable: true,
        },
        {
          label: 'Action',
          field: 'quick',
          width: '3%',
          display(row: rowData) {
            return (`<button type="button" data-id="${row.id}" data-email="${row.email}" class="is-rows-el remove-btn">Supprimer</button>`);
          },
        },
      ],
      rows: [] as Array<rowData>,
      totalRecordCount: 0,
      sortable: {
        order: 'id',
        sort: 'asc',
      },
      messages: {
        pagingInfo: 'Showing {0}-{1} of {2}',
        pageSizeChangeLabel: 'Row count:',
        gotoPageLabel: 'Go to page:',
        noDataAvailable: 'No data',
      },
    });

    /**
     * lis all users
     */
    const listAllUsers = async () => {
      const data: rowData[] = [];
      const list = JSON.parse(await listUsers());
      const offst = 0;
      const limit = list.users.length;
      for (let i = offst; i < limit; i += 1) {
        data.push({
          id: i,
          name: `USER ${i}`,
          email: `${list.users[i].email}`,
          role: `${list.users[i].role}`,
        });
      }
      table.rows = data;
      table.totalRecordCount = list.users.length;
    };

    /**
     * Table search finished event
     */
    const tableLoadingFinish = (elements: Array<HTMLElement>) => {
      console.log('elem = ', elements);
      table.isLoading = false;
      Array.prototype.forEach.call(elements, function (element: HTMLElement) {
        if (element.classList.contains('remove-btn')) {
          element.addEventListener('click', function () {
            console.log(`${this.dataset.id} name-btn click!!`);
          });
        }
      });
    };

    /**
     * Table search event
     */
    const doSearch = (offset: number, limit: number, order: string, sort: string) => {
      let thislimit = limit;
      table.isLoading = true;
      const RowUsers = table.rows;
      let result;
      setTimeout(() => {
        table.isReSearch = (offset === undefined);

        if (offset >= 10 || thislimit >= 20) {
          thislimit = 20;
        }
        if (order === 'id') {
          if (sort === 'asc') {
            result = RowUsers.sort((a, b) => a.id! - b.id!);
          } else {
            result = RowUsers.sort((a, b) => b.id! - a.id!);
          }
        }
        if (order === 'email') {
          if (sort === 'asc') {
            result = RowUsers.sort((a, b) => ((a.email! < b.email!) ? 1 : -1));
          } else {
            result = RowUsers.sort((a, b) => ((a.email! > b.email!) ? 1 : -1));
          }
        }
        if (order === 'role') {
          if (sort === 'asc') {
            result = RowUsers.sort((a, b) => ((a.role! < b.role!) ? 1 : -1));
          } else {
            result = RowUsers.sort((a, b) => ((a.role! > b.role!) ? 1 : -1));
          }
        }
        // table.isLoading = false;
        table.rows = result;
        table.totalRecordCount = 20;
        table.sortable.order = order;
        table.sortable.sort = sort;
      }, 600);
    };

    /**
     * Row checked event
     */
    const updateCheckedRows = (rowsKey: number) => {
      console.log('rowsKey = ', rowsKey);
    };

    listAllUsers();

    return (
      {
        table,
        doSearch,
        tableLoadingFinish,
        updateCheckedRows,
      });
  }
});
</script>

Hidden Column

Hey @linmasahiro is it possible to have a hidden column?
A column that is not visible in the table but whose data can be used in a v-slot for example.
This will prevent the need for hitting the server api again just to get details for example which
I want in a hover over my summary field. Details is not shown in the Table columns but that data should be available to be used.

Request grouping

Hello,

Is it possible to add groups to the table, where rows would be grouped by some identifier ( name of the group )?

image not loading

hello,

thank you for the component,
but it seems like images in rows are not getting loaded
image
image

all the best,

How to sort etc with Data from supabase

Hello, @linmasahiro I have data from supabase using their interface and not axios.
what I want to achieve ,

  1. Get paginated data and be able to change page size and get more or less data from supabase
  2. Get sort and search working with the data on the client side to reduce server hits
    what I have been able to achieve so far is to get the initial data showing.
    I have tried lots of the examples but cant get sorting to work. table just shows loading when I click the table headers.

My code below, please show how I can achieve this with your package

// async function fetchTickets() {
// let { data: tickets, error } = await client
//     .from('tickets')
//     .select('*')
// console.log("๐Ÿš€ ~ file: TicketerTicketsTable.vue ~ line 8 ~ data", tickets)
// return tickets
// }

// const fetchTickets = async (offst, limit) => {
//     offst = offst + 1;
//     let { data: tickets, error } = await client
//         .from('tickets')
//         .select('*')
//     // console.log("๐Ÿš€ ~ file: TicketerTicketsTable.vue ~ line 33 ~ fetchTickets ~ tickets", tickets)

//     return tickets;
// }

// fetchTickets()

// Init Your table settings
const table = reactive({
    isLoading: false,
    columns: [
        {
            label: "ID",
            field: "id",
            width: "5%",
            sortable: true,
            isKey: true,
        },
        {
            label: "Summary",
            field: "summary",
            width: "20%",
            sortable: true,
        },
        {
            label: "Status",
            field: "status",
            width: "10%",
            sortable: true,
        },
        {
            label: "Priority",
            field: "priority",
            width: "10%",
            sortable: true,
        },        
        {
            label: "Date from",
            field: "date_from",
            width: "10%",
            sortable: true,
        },       
    ],
    rows: [],
    totalRecordCount: computed(() => {
        return table.rows.length;
    }),
    // totalRecordCount: 3,
    sortable: {
        order: "id",
        sort: "asc",
    },
});

let { data: tickets, error } = await client
    .from('tickets')
    .select('*')

table.rows = tickets
// table.totalRecordCount = 

/**
   * Search Event
   */
const doSort = (offset, limit, order, sort) => {
    console.log("do sort called")
    // table.isLoading = true;
    table.isReSearch = offset == undefined ? true : false;
    // if (offset >= 10 || limit >= 20) {
    //     limit = 20;
    // }
    // if (sort == "asc") {
    //     table.rows = fetchTickets(offset, limit);
    // } else {
    //     table.rows = fetchTickets(offset, limit);
    // }
    table.rows = tickets;
    // table.totalRecordCount = 20;
    table.sortable.order = order;
    table.sortable.sort = sort;
};
// First get data
doSort(0, 10, 'id', 'asc')

// template code
 <table-lite :has-checkbox="true" :is-loading="table.isLoading" :columns="table.columns" :rows="table.rows"
            :total="table.totalRecordCount" :sortable="table.sortable" @do-search="doSort"
            @is-finished="table.isLoading = false" @return-checked-rows="updateCheckedRows" @row-clicked="rowClicked">
        </table-lite>

Bug display with data object

I have such a piece of data but it cannot display

_id: 1, name: "post_1", cate_id: [{ _id:8, name: video, },{ _id:1, name:post }]
how does it show with the depth of object data in array rows ?
I see it showing with string [Object] when working with data mongoose it doesn't work as expected with row.cate[0].name

Table sort is not working.

The sort feature in this, sometimes works, sometimes not also I tried your demo code in my my code, it also works sometimes, sometimes not. Could you fix and stabilize this feature?

emit of "is-finished" is not triggered on the first render

First, thank you for developing this component, I like the inspiration from the DataTables library.
When I use the component, the emit of is-finished does not get triggered on the first render, but it does occur if you go to different pages.

Server Side Pagination

Hello, I'm not entirely sure how to handle server side pagination. For example, using an API where you pull data like /api/some_endpoint?page=2

Could you provide some instruction on this, or point to me the relevant section in the README? Thanks!

Positionable headers

Hello,

It would be great if you could position headers of each column ( left ( default ), center, right ). We put numbers to the right and I dont see any option to do it for headers or to stylize headers individually.

Also, this table is really nice and easy to use, really great work.

Failed to resolve component: vue-table-lite

Hi,
First, thank you for your work.
I have some issues to integrate your code. I am beginner level btw.
[Vue warn]: Failed to resolve component: vue-table-lite

I am using Vue3 with Ts and I followed the documentation.

Here is my code:

<template>
  <vue-table-lite
    :is-static-mode='false'
    :has-checkbox='true'
    :is-loading='table.isLoading'
    :is-re-search='table.isReSearch'
    :columns='table.columns'
    :rows='table.rows'
    :total='table.totalRecordCount'
    :sortable='table.sortable'
    :messages='table.messages'
    @do-search="doSearch"
    @is-finished='tableLoadingFinish'
    @return-checked-row='updateCheckedRows'
  />
</template>

<script lang="ts">
import { reactive } from 'vue';
import VueTableLite from 'vue3-table-lite';

export default {
  name: 'AccountsTab',
  setup() : unknown {
    const table = reactive({
      isLoading: false,
      isReSearch: false,
      columns: [
        {
          label: 'ID',
          field: 'id',
          width: '3%',
          sortable: true,
          isKey: true,
        },
        {
          label: 'Name',
          field: 'name',
          width: '10%',
          sortable: true,
          display: function display(row) {
            return (
              `<a href="#" data-id="${row.user_id}" class="name-btn">${row.name}</button>`
            );
          },
        },
        {
          label: 'Email',
          field: 'email',
          width: '15%',
          sortable: true,
        },
        {
          label: '',
          field: 'quick',
          width: '10%',
          display: function display(row) {
            return (
              `<button type="button" data-id="${row.user_id}" class="quick-btn">Button</button>`
            );
          },
        },
      ],
      rows: [
        {
          id: 1,
          name: 'TEST1'
        },
        {
          id: 2,
          name: 'TEST2'
        }
      ],
      totalRecordCount: 2,
      sortable: {
        order: 'id',
        sort: 'asc',
      },
      messages: {
        pagingInfo: 'Showing {0}-{1} of {2}',
        pageSizeChangeLabel: 'Row count:',
        gotoPageLabel: 'Go to page:',
        noDataAvailable: 'No data',
      },
    });

    const doSearch = (offset, limit, order, sort) => {
      table.isLoading = true;
      table.isReSearch = offset === undefined;
      // do your search event to get newRows and new Total
      table.rows = newRows;
      table.totalRecordCount = newTotal;
      table.sortable.order = order;
      table.sortable.sort = sort;
    };

    const tableLoadingFinish = (elements) => {
      table.isLoading = false;
      Array.prototype.forEach.call(elements, function load(element) {
        if (element.classList.contains('name-btn')) {
          element.addEventListener('click', function click() {
            // do your click event
            console.log(`${this.dataset.id} name-btn click!!`);
          });
        }
        if (element.classList.contains('quick-btn')) {
          // do your click event
          element.addEventListener('click', function click() {
            console.log(`${this.dataset.id} quick-btn click!!`);
          });
        }
      });
    };

    const updateCheckedRows = (rowsKey) => {
      // do your checkbox click event
      console.log(rowsKey);
    };
    return (
      {
        accountsList,
        table,
        doSearch,
        tableLoadingFinish,
        updateCheckedRows,
      });
  }
};
</script>

<style>    
</style>

Best regards,

Highlightjs doesn't work in display functions

I'm trying to use the highlightjs plugin, found here Vue-Plugin, to markup table cell contents but it doesn't appear to display anything at all.

                                 {
                                    label: "Example",
                                    field: "example",
                                    width: "30%",
                                    sortable: false,
                                    display: function (row) {
                                        return (
                                            '<highlightjs language="javascript" code="console.log(1);"/>'
                                        );
                                    },

Here is how I'm trying to call it. If I move the highlightjs component into my Vue template it displays fine so it's not an issue of highlightjs not registering properly. There don't seem to be any errors in the console so I'm not entirely sure how to go about debugging this. Do you have any idea what the issue might be?

Suggest removal of .card wrappers

The div.card, div.cart-body, .div.card-title wrappers are causing problems with alignment in my app. I suggest removing them for a few reasons:

  • They are unneccesary and can cause styling conflicts
  • Naming a div .card is too generic which may easily conflict with other styles since there is not a parent wrapper (and adding one is also unneccesary)
  • Although title can be passed via props, this isn't even documented in the documentation and also doesn't add any value to this library

Return rows from API

Hi, thank you for sharing your work.
I'm new to Vue and I'm having trouble in returning data from my API. I'm using django for the backend.
It would be very helpful to have a more detailed documentation on how to use this, and more examples.

Custom cell content

It would be nice to be able to customize the content for each column, for example to make it a link:

<table-list :row="..." ...>
   <table-column field="name">
         <router-link ...>{{columnValue}}</router-link> 
   </table>-column>
</table-list>

another options would be to allow a template in the column definitions:

let columns = [
  {
     field:'name',
    label: 'Name',
    template: ' <router-link>{{value}}</router-link>' 
  }
]

add events

I'm working with my team using this package but we didn't find event handling yet (v-on or @)

Share the tableLoadingFinish function between several tables.

If I had 2 or more tables components on the same page. Is there anyway I could use the same 'tableLoadingFinish' function between them all but reference the individual table that called it. Currently I am having to duplicate the function 'tableLoadingFinish', 'tableLoadingFinish2' etc. Same for 'table.isLoading = false;' , 'table2.isLoading = false;'

const tableLoadingFinish = (elements) => {
  table.isLoading = false;
  Array.prototype.forEach.call(elements, function (element) {
    if (element.classList.contains("name-btn")) {
      element.addEventListener("click", function () {
        // do your click event
        console.log(this.dataset.id + " name-btn click!!");
      });
    }
    if (element.classList.contains("quick-btn")) {
      // do your click event
      element.addEventListener("click", function () {
        console.log(this.dataset.id + " quick-btn click!!");
      });
    }
  });
};

Cant change page without using $refs

Hey again!

I was wondering if there was a better way to trigger a page change without using $refs to trigger prevPage() ?

I currently have to trigger it if i delete everything on the table page.

Alternatively would it be possible to add the functionality to change the page number via the page prop rather than being locked into using the buttons?

Thanks for your help,
Alex

Suggestion to add selected item event

I would like to suggest the option of adding an event called "selected" to manipulate the records that are selected within the table. It would look like this.

<tr
       @click="$emit('selected', row)"
        v-for="(row, i) in rows"
        :key="i"
        class="vtl-tbody-tr"
        :class="typeof rowClasses === 'function' ? rowClasses(row) : rowClasses"
>

Both the static and dynamic tables should include this event as it is very useful.

Sorting not working

I'm loading a simple API with a list of name/description.
Sorting the rows by name doesn't work, asc or desc, they are always in the same order

Paging bug on static-mode

On static-mode, will not be back to first-page after filtered keyword.

Steps:

  1. enter test2 in filter.
  2. change to page2
  3. enter test22 in filter.

Demo page broken

It looks like none of the examples on your demo page are working.

Fix documentation

It would be good, to expand on the documentation.
There surely is quite some that isnt in the documentation, like in props, there isnt the prop to control page size.
Also, there arent all triggers explained for @do-search as it triggers not just for search/filter, but also sorting and page changing. That would be great to add for better clarity.

Ability to customized look

Just being able to specify a CSS class for the various elements would be enough.

Or is it possible already to customize look?

Suggest to add dynamic row classes

Please add the possibility of dynamic classes for the row.

For example, I want to change background color depending of row property.

in TableLite.vue add prop 'rowClasses'

    rowClasses: {
      type: Function,
      default: () => []
    },

and add :class="rowClasses(row) to 'tr' rendering template.

Now in component using I can write function:

      rowClasses(row) {
          let classes = [];
          if (row.category.indexOf('critical') > 0) {
              classes.push('table-danger');
          }
          return classes;
      },

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.