From 878be3e9de715e01d76aa45761ba7acb5d14568e Mon Sep 17 00:00:00 2001 From: Albert Kaaman Date: Fri, 19 Jul 2019 23:58:07 +0200 Subject: [PATCH] feat(VDataTable): change data-table scoped slot props structure (#7585) * feat(VDataTable): change data-table scoped slot props structure make it easier to use props in scoped slots * fix(VDataTable): incorrect api information * fix(VDataTable): fix internal select/expand functionality --- .../api-generator/src/maps/v-data-iterator.js | 28 ++++--------- .../api-generator/src/maps/v-data-table.js | 30 ++++++-------- packages/api-generator/src/maps/v-data.js | 6 +-- .../src/lang/en/components/DataTables.json | 17 ++++---- .../components/VDataIterator/VDataIterator.ts | 20 ++-------- .../__tests__/VDataIterator.spec.ts | 4 +- .../src/components/VDataTable/VDataTable.ts | 39 +++++++------------ .../VDataTable/__tests__/VDataTable.spec.ts | 1 - .../__snapshots__/VDataTable.spec.ts.snap | 10 ++--- 9 files changed, 56 insertions(+), 99 deletions(-) diff --git a/packages/api-generator/src/maps/v-data-iterator.js b/packages/api-generator/src/maps/v-data-iterator.js index 1b542b53549..d66a3fb33d7 100644 --- a/packages/api-generator/src/maps/v-data-iterator.js +++ b/packages/api-generator/src/maps/v-data-iterator.js @@ -29,22 +29,10 @@ const DataIteratorSlots = [ const DataIteratorItemScopedProps = { item: 'any', - select: { - props: { - value: 'boolean', - }, - on: { - input: '(v: boolean) => void', - }, - }, - expand: { - props: { - value: 'boolean', - }, - on: { - input: '(v: boolean) => void', - }, - }, + select: '(v: boolean) => void', + isSelected: 'boolean', + expand: '(v: boolean) => void', + isExpanded: 'boolean', } const DataIteratorScopedSlots = [ @@ -52,10 +40,10 @@ const DataIteratorScopedSlots = [ name: 'default', props: { ...DataDefaultScopedSlotProps, - isSelected: 'boolean', - select: '(item: any, value: boolean) => void', - isExpanded: 'boolean', - expand: '(item: any, value: boolean) => void', + isSelected: '(item: any) => boolean', + select: '(item: any, value: boolean): void', + isExpanded: '(item: any) => boolean', + expand: '(item: any, value: boolean): void', }, source: 'data-iterator', }, diff --git a/packages/api-generator/src/maps/v-data-table.js b/packages/api-generator/src/maps/v-data-table.js index 83c8d1b970d..ea0c7289efa 100644 --- a/packages/api-generator/src/maps/v-data-table.js +++ b/packages/api-generator/src/maps/v-data-table.js @@ -1,5 +1,5 @@ const { DataDefaultScopedSlotProps, DataOptions, DataProps } = require('./v-data') -const { DataIteratorEvents, DataIteratorProps } = require('./v-data-iterator') +const { DataIteratorEvents, DataIteratorProps, DataIteratorItemScopedProps } = require('./v-data-iterator') const { DataFooterPageTextScopedProps } = require('./v-data-footer') const TableHeader = { @@ -38,32 +38,27 @@ const DataTableHeaderColumnScopedProps = { header: 'TableHeader', } +const DataTableItemScopedProps = { + ...DataIteratorItemScopedProps, + headers: 'TableHeader[]', +} + const DataTableItemColumnScopedProps = { item: 'any', header: 'TableHeader', value: 'any', } -const DataTableSelectScopedProps = { - item: 'any', +const DataTableHeaderSelectScopedProps = { props: { value: 'boolean', + indeterminate: 'boolean', }, on: { input: '(value: boolean) => void', }, } -const DataTableExpandScopedProps = { - item: 'any', - props: { - expanded: 'boolean', - }, - on: { - click: '(value: boolean) => void', - }, -} - const DataTableExpandedItemScopedProps = { item: 'any', headers: 'TableHeader[]', @@ -75,17 +70,16 @@ const DataTableSlots = [ { name: 'footer', props: DataDefaultScopedSlotProps }, { name: 'footer.page-text', props: DataFooterPageTextScopedProps }, { name: 'header', props: DataTableHeaderScopedProps }, - { name: 'header.data-table-select', props: DataTableSelectScopedProps }, - { name: 'header.data-table-expand', props: DataTableExpandScopedProps }, + { name: 'header.data-table-select', props: DataTableHeaderSelectScopedProps }, { name: 'header.', props: DataTableHeaderColumnScopedProps }, { name: 'top', props: DataDefaultScopedSlotProps }, { name: 'progress', props: DataDefaultScopedSlotProps }, { name: 'group', props: DataDefaultScopedSlotProps }, { name: 'group.header', props: DataDefaultScopedSlotProps }, { name: 'group.summary', props: DataDefaultScopedSlotProps }, - { name: 'item', props: DataDefaultScopedSlotProps }, - { name: 'item.data-table-select', props: DataTableSelectScopedProps }, - { name: 'item.data-table-expand', props: DataTableExpandScopedProps }, + { name: 'item', props: DataTableItemScopedProps }, + { name: 'item.data-table-select', props: DataTableItemScopedProps }, + { name: 'item.data-table-expand', props: DataTableItemScopedProps }, { name: 'item.', props: DataTableItemColumnScopedProps }, { name: 'expanded-item', props: DataTableExpandedItemScopedProps }, ] diff --git a/packages/api-generator/src/maps/v-data.js b/packages/api-generator/src/maps/v-data.js index 662950bde4e..84ceebf2e27 100644 --- a/packages/api-generator/src/maps/v-data.js +++ b/packages/api-generator/src/maps/v-data.js @@ -44,9 +44,9 @@ const DataDefaultScopedSlotProps = { items: 'any[]', pagination: DataPagination, options: DataOptions, - updateOptions: '(obj: any) => void', - sort: '(value: string) => void', - group: '(value: string) => void', + updateOptions: '(obj: any): void', + sort: '(value: string): void', + group: '(value: string): void', groupedItems: 'Record', } diff --git a/packages/docs/src/lang/en/components/DataTables.json b/packages/docs/src/lang/en/components/DataTables.json index 5b544113bbd..a1968799f71 100644 --- a/packages/docs/src/lang/en/components/DataTables.json +++ b/packages/docs/src/lang/en/components/DataTables.json @@ -123,21 +123,22 @@ }, "slots": { "v-data-table": { + "item": "Slot to replace the default rendering of a row", + "item.data-table-select": "Slot to replace the default `v-simple-checkbox` used when selecting rows", + "item.data-table-expand": "Slot to replace the default `v-icon` used when expanding rows", + "item.": "Slot to customize a specific column", + "expanded-item": "Slot to customize expanded rows", "body": "Slot to replaces the default table ``", "body.append": "Appends elements to the end of the default table ``", "body.prepend": "Prepends elements to the end of the default table ``", - "expanded-item": "Slot to customize expanded rows", "footer": "Slot to add a custom footer", + "footer.page-text": "Slot to customize footer page text", + "header": "Slot to add a custom header", + "header.": "Slot to customize a specific header column", + "header.data-table-select": "Slot to replace the default `v-simple-checkbox` in header", "group": "Slot to replace the default rendering of grouped rows", "group.header": "Slot to customize the default rendering of group headers", "group.summary": "Slot to customize the default rendering of group summaries", - "header": "Slot to add a custom header", - "header.": "Slot to customize a specific header column", - "header.dataTableSelect": "Slot to replace the default `v-simple-checkbox` in header", - "item": "Slot to replace the default rendering of a row", - "item.": "Slot to customize a specific column", - "item.dataTableExpand": "Slot to replace the default `v-icon` used when expanding rows", - "item.dataTableSelect": "Slot to replace the default `v-simple-checkbox` used when selecting rows", "top": "Slot to add content above the table", "progress": "Slot to replace the default `` component" }, diff --git a/packages/vuetify/src/components/VDataIterator/VDataIterator.ts b/packages/vuetify/src/components/VDataIterator/VDataIterator.ts index 4b4f0f71e84..272bb08df58 100644 --- a/packages/vuetify/src/components/VDataIterator/VDataIterator.ts +++ b/packages/vuetify/src/components/VDataIterator/VDataIterator.ts @@ -169,22 +169,10 @@ export default Themeable.extend({ createItemProps (item: any) { const props = { item, - select: { - props: { - value: this.isSelected(item), - }, - on: { - input: (v: boolean) => this.select(item, v), - }, - }, - expand: { - props: { - value: this.isExpanded(item), - }, - on: { - input: (v: boolean) => this.expand(item, v), - }, - }, + select: (v: boolean) => this.select(item, v), + isSelected: this.isSelected(item), + expand: (v: boolean) => this.expand(item, v), + isExpanded: this.isExpanded(item), } return props diff --git a/packages/vuetify/src/components/VDataIterator/__tests__/VDataIterator.spec.ts b/packages/vuetify/src/components/VDataIterator/__tests__/VDataIterator.spec.ts index d7160ffcc90..4b31b70a0c3 100644 --- a/packages/vuetify/src/components/VDataIterator/__tests__/VDataIterator.spec.ts +++ b/packages/vuetify/src/components/VDataIterator/__tests__/VDataIterator.spec.ts @@ -116,7 +116,7 @@ describe('VDataIterator.ts', () => { id: props.item.text, }, on: { - click: () => props.select.on.input(true), + click: () => props.select(true), }, }, [props.item.text]) }, @@ -151,7 +151,7 @@ describe('VDataIterator.ts', () => { id: props.item.text, }, on: { - click: () => props.expand.on.input(true), + click: () => props.expand(true), }, }, [props.item.text]) }, diff --git a/packages/vuetify/src/components/VDataTable/VDataTable.ts b/packages/vuetify/src/components/VDataTable/VDataTable.ts index 8cb395e8b8c..61b8aa6be02 100644 --- a/packages/vuetify/src/components/VDataTable/VDataTable.ts +++ b/packages/vuetify/src/components/VDataTable/VDataTable.ts @@ -384,47 +384,34 @@ export default VDataIterator.extend({ genDefaultSimpleRow (item: any, classes: string | string[] | object | null = null): VNode { const scopedSlots = getPrefixedScopedSlots('item.', this.$scopedSlots) + const data = this.createItemProps(item) + if (this.showSelect) { - const data = { - item, + const slot = scopedSlots['data-table-select'] + scopedSlots['data-table-select'] = slot ? () => slot(data) : () => this.$createElement(VSimpleCheckbox, { + staticClass: 'v-data-table__checkbox', props: { - value: this.isSelected(item), + value: data.isSelected, }, on: { - input: (v: any) => this.select(item, v), + input: (val: boolean) => data.select(val), }, - } - - const slot = scopedSlots['data-table-select'] - scopedSlots['data-table-select'] = slot ? () => slot(data) : () => this.$createElement(VSimpleCheckbox, { - staticClass: 'v-data-table__checkbox', - ...data, }) } - const expanded = this.isExpanded(item) - if (this.showExpand) { - const data = { - item, - props: { - expanded, + const slot = scopedSlots['data-table-expand'] + scopedSlots['data-table-expand'] = slot ? () => slot(data) : () => this.$createElement(VIcon, { + staticClass: 'v-data-table__expand-icon', + class: { + 'v-data-table__expand-icon--active': data.isExpanded, }, on: { click: (e: MouseEvent) => { e.stopPropagation() - this.expand(item, !expanded) + data.expand(!data.isExpanded) }, }, - } - - const slot = scopedSlots['data-table-expand'] - scopedSlots['data-table-expand'] = slot ? () => slot(data) : () => this.$createElement(VIcon, { - staticClass: 'v-data-table__expand-icon', - class: { - 'v-data-table__expand-icon--active': expanded, - }, - ...data, }, [this.expandIcon]) } diff --git a/packages/vuetify/src/components/VDataTable/__tests__/VDataTable.spec.ts b/packages/vuetify/src/components/VDataTable/__tests__/VDataTable.spec.ts index ce1acf289bd..2b361faba8b 100644 --- a/packages/vuetify/src/components/VDataTable/__tests__/VDataTable.spec.ts +++ b/packages/vuetify/src/components/VDataTable/__tests__/VDataTable.spec.ts @@ -197,7 +197,6 @@ describe('VDataTable.ts', () => { 'update:expanded': expand, }, }) - // const expand = jest.spyOn(wrapper.vm, 'expand') expect(wrapper.html()).toMatchSnapshot() const expandIcon = wrapper.findAll('.v-data-table__expand-icon').at(0) diff --git a/packages/vuetify/src/components/VDataTable/__tests__/__snapshots__/VDataTable.spec.ts.snap b/packages/vuetify/src/components/VDataTable/__tests__/__snapshots__/VDataTable.spec.ts.snap index b406302b75f..1d282669bb2 100644 --- a/packages/vuetify/src/components/VDataTable/__tests__/__snapshots__/VDataTable.spec.ts.snap +++ b/packages/vuetify/src/components/VDataTable/__tests__/__snapshots__/VDataTable.spec.ts.snap @@ -2308,19 +2308,19 @@ exports[`VDataTable.ts should render with item scoped slot 1`] = `
- {"item":{"name":"Frozen Yogurt","calories":159,"fat":6,"carbs":24,"protein":4,"iron":"1%"},"select":{"props":{"value":false},"on":{}},"expand":{"props":{"value":false},"on":{}},"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]} + {"item":{"name":"Frozen Yogurt","calories":159,"fat":6,"carbs":24,"protein":4,"iron":"1%"},"isSelected":false,"isExpanded":false,"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]}
- {"item":{"name":"Ice cream sandwich","calories":237,"fat":9,"carbs":37,"protein":4.3,"iron":"1%"},"select":{"props":{"value":false},"on":{}},"expand":{"props":{"value":false},"on":{}},"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]} + {"item":{"name":"Ice cream sandwich","calories":237,"fat":9,"carbs":37,"protein":4.3,"iron":"1%"},"isSelected":false,"isExpanded":false,"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]}
- {"item":{"name":"Eclair","calories":262,"fat":16,"carbs":23,"protein":6,"iron":"7%"},"select":{"props":{"value":false},"on":{}},"expand":{"props":{"value":false},"on":{}},"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]} + {"item":{"name":"Eclair","calories":262,"fat":16,"carbs":23,"protein":6,"iron":"7%"},"isSelected":false,"isExpanded":false,"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]}
- {"item":{"name":"Cupcake","calories":305,"fat":3.7,"carbs":67,"protein":4.3,"iron":"8%"},"select":{"props":{"value":false},"on":{}},"expand":{"props":{"value":false},"on":{}},"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]} + {"item":{"name":"Cupcake","calories":305,"fat":3.7,"carbs":67,"protein":4.3,"iron":"8%"},"isSelected":false,"isExpanded":false,"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]}
- {"item":{"name":"Gingerbread","calories":356,"fat":16,"carbs":49,"protein":3.9,"iron":"16%"},"select":{"props":{"value":false},"on":{}},"expand":{"props":{"value":false},"on":{}},"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]} + {"item":{"name":"Gingerbread","calories":356,"fat":16,"carbs":49,"protein":3.9,"iron":"16%"},"isSelected":false,"isExpanded":false,"headers":[{"text":"Dessert (100g serving)","align":"left","sortable":false,"value":"name"},{"text":"Calories","value":"calories"},{"text":"Fat (g)","value":"fat"},{"text":"Carbs (g)","value":"carbs"},{"text":"Protein (g)","value":"protein"},{"text":"Iron (%)","value":"iron"}]}