linmasahiro / vue3-table-lite

A simple and lightweight data table component for Vue.js 3. Features sorting, paging, row check, dynamic data rendering, supported TypeScript, and more.
https://vue3-lite-table.vercel.app/
MIT License
248 stars 73 forks source link

lost event click after dosearch #27

Closed mambari closed 2 years ago

mambari commented 2 years ago

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>
linmasahiro commented 2 years ago

Hi, @mambari If you want to filter data on client, you should be use static-mode. I fixed your code on here, and it good work.

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

<script lang="ts">
import { defineComponent, reactive, computed } 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();

    // Init Your table settings
    const table = reactive({
      isLoading: 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: computed((): number => {
        return table.rows.length;
      }),
      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 () => {
      table.isLoading = true;
      const data: rowData[] = [];
      for (let i = 0; i < 126; i++) {
        data.push({
          id: i,
          name: "TEST" + i,
          email: "test" + i + "@example.com",
          role: "ADMIN",
        });
      }
      // To Mehdi: restore your source plz.
      // 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 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!!`);
          });
        }
      });
    };

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

    listAllUsers();

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

※ You can reference Filter example or Asynchronous filter example to helpful you.

mambari commented 2 years ago

Hi, thank you for your help 🙏 . I copy past your solution but I get that (stuck with loading): (But I am with "vue3-table-lite": "^1.0.7" ) 2022-02-03 at 00 31

linmasahiro commented 2 years ago

Hi, @mambari

Hi, thank you for your help 🙏 . I copy past your solution but I get that (stuck with loading): (But I am with "vue3-table-lite": "^1.0.7" )

Has a tableLoadingFinish method not working on static-mode bug on version 1.0.7, fixed on v1.0.8. So upgrade to upper v1.0.8, thanks.

mambari commented 2 years ago

Thank you so much. I updated and It works like a charm.