HC200ok / vue3-easy-data-table

A customizable and easy-to-use data table component made with Vue.js 3.x
MIT License
523 stars 104 forks source link

Cloning items #139

Open wozni opened 1 year ago

wozni commented 1 year ago

Hello

First of all, thank you very much for such an excellent component! It enables a straightforward migration for our project as we rely heavily on displaying data in tables. However, I spotted a minor issue when it comes to working with column templates and pagination - in https://github.com/HC200ok/vue3-easy-data-table/blob/main/src/hooks/usePageItems.ts#L39 we are receiving a copy original item properties instead of the item itself. This prevents us from using functions and properties of the original object - we are passing quite complex viewmodels to the grid. Is it possible to expose the original item and additional fields in one object, for example { item, checkbox, index }?

Thank you for your work :)

HC200ok commented 1 year ago

@wozni Do you mean not using spread syntax (...) like:

Yes:

return itemsInPage.value.map((item, index) => ({ index: currentPageFirstIndex.value + index, item }));

No:

return itemsInPage.value.map((item, index) => ({ index: currentPageFirstIndex.value + index, ...item }));
wozni commented 1 year ago

Yes, exactly

HC200ok commented 1 year ago

@wozni Could you provide a demo Items data so I can test it?

wozni commented 1 year ago

It's easy to reproduce, try to call a function on an item in the column template. The spread syntax does not copy functions and properties.

export class User {
  constructor(public firstName: string, public lastName: string) {
  }

  get displayName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

const users: User[] = [new User("John","Smith")]
const headers: Header[] = [
    {text: "Name", value: "displayName", sortable: true}
]
 <EasyTable
      :headers="headers"
      :items="users"      
 >
 <template #item-displayName="user" >
    {{user.displayName}}
 </template>
 </EasyTable>
HC200ok commented 1 year ago

I tried to use shallowClone function:

function shallowClone(obj: Item): Item {
  return Object.create(
    Object.getPrototypeOf(obj),
    Object.getOwnPropertyDescriptors(obj),
  );
}

to clone every property of the item including get property instead of using spread syntax (...) or JSON.parse(JSON.stringfy(item)), and I console the final pageItems in the setup function of table component here: https://github.com/HC200ok/vue3-easy-data-table/blob/d698346795d1edf72e7a28ce61a2be69dba3ebbe/src/components/DataTable.vue#L489

items including User instance was consoled correctly:

截屏2022-11-10 下午11 06 36

but finally, Vue template seems not to render by using the original item:

截屏2022-11-10 下午11 09 30

I will keep google it and try to solve it.