Skip to content

Commit

Permalink
chore(lib): update Table
Browse files Browse the repository at this point in the history
- The `Table` component and related components are updated. Changes
  sufficient to render the documentation page of the `Table`
  component are made. A commit of changes on the code of the
  documentation page will follow this commit.
- In `src/components/table/Table.vue`,
    - `$scopedSlots` --> `$slots` because `$scopedSlots` is integrated
      into `$slots` on Vue 3. Unnecessary check of `$scopedSlots` is
      removed.
    - `defaultSlots` is no longer a copy of `$scopedSlots.default`
      because `$scopedSlots` no longer exists on Vue 3. Unfortunately,
      copying `$slots.default` did not work because I could not figure
      out how to obtain a component instance from a slot. As a
      workaround, `TableColumn` registers itself to the parent table
      by calling `_registerTableColumn` newly introduced to `Table`.
      `TableColumn` calls `_unregisterTableColumn` that is also
      newly introduced to `Table` when it is about to be unmounted.
      `refreshSlots` is removed.
    - The `footer` slot supports a fragment, i.e., template. The
      footer section of the Table documentation needs this change.
- In `src/components/table/TableColumn.vue`,
    - `TableColumn` calls `_registerTableColumn` when it is created
      (see changes on `Table`).
    - `TableColumn` calls `_unregisterTableColumn` when it is about
      to be unmounted (see changes on `Table`).
    - `$destroy` is removed because Vue 3 no longer supports it.
- In `src/components/table/TableMobileSort.vue`,
    - Not a component instance but its index is assigned to `value`
      of an `option` element. Because Vue 3 crashes when a component
      instance is assigned to `value` of an `option` element. The
      following conversion is added to keep the interface of
      `TableMobileSort` the same,
        - `sortMultipleSelect` ⟷ `sortMultipleSelectIndex`
        - `mobileSort` ⟷ `mobileSortIndex`
    - `key` binding is moved to `template` with `v-for`.
- In `src/components/table/mockTableColumn`,
    - `$scopedSlots` --> `$slots` because `SlotComponent` migrates to
      Vue 3.
- In `src/utils/SlotComponent.js`,
    - `render` no longer refers to `$scopedSlots` but `$slots` because
      `$scopedSlots` no longer exists on Vue 3.
    - TODO: `isVueComponent` has to be replaced.
- Common,
    - Automatic ESLint fix is applied.
    - Manually removes `.native` on event handlers.
  • Loading branch information
kikuomax committed Jul 7, 2023
1 parent fe60329 commit 34e4f7a
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 46 deletions.
66 changes: 37 additions & 29 deletions src/components/table/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,16 @@
<template v-if="headerCheckable">
<slot
name="check-all"
:isAllChecked="isAllChecked"
:isAllUncheckable="isAllUncheckable"
:checkAll="checkAll">
:is-all-checked="isAllChecked"
:is-all-uncheckable="isAllUncheckable"
:check-all="checkAll"
>
<b-checkbox
autocomplete="off"
:value="isAllChecked"
:model-value="isAllChecked"
:type="checkboxType"
:disabled="isAllUncheckable"
@change.native="checkAll"
@change="checkAll"
/>
</slot>
</template>
Expand Down Expand Up @@ -105,7 +106,7 @@
'is-centered': column.centered
}"
>
<template v-if="column.$scopedSlots && column.$scopedSlots.header">
<template v-if="column.$slots.header">
<b-slot-component
:component="column"
scoped
Expand Down Expand Up @@ -165,15 +166,16 @@
<template v-if="headerCheckable">
<slot
name="check-all"
:isAllChecked="isAllChecked"
:isAllUncheckable="isAllUncheckable"
:checkAll="checkAll">
:is-all-checked="isAllChecked"
:is-all-uncheckable="isAllUncheckable"
:check-all="checkAll"
>
<b-checkbox
autocomplete="off"
:value="isAllChecked"
:model-value="isAllChecked"
:type="checkboxType"
:disabled="isAllUncheckable"
@change.native="checkAll"
@change="checkAll"
/>
</slot>
</template>
Expand All @@ -195,7 +197,7 @@
}"
>
<template
v-if="column.$scopedSlots && column.$scopedSlots.subheading"
v-if="column.$slots.subheading"
>
<b-slot-component
:component="column"
Expand Down Expand Up @@ -225,8 +227,7 @@
<div class="th-wrap">
<template v-if="column.searchable">
<template
v-if="column.$scopedSlots
&& column.$scopedSlots.searchable"
v-if="column.$slots.searchable"
>
<b-slot-component
:component="column"
Expand Down Expand Up @@ -294,7 +295,7 @@
>
<b-checkbox
autocomplete="off"
:value="isRowChecked(row)"
:model-value="isRowChecked(row)"
:type="checkboxType"
:disabled="!isRowCheckable(row)"
@click.prevent.stop="checkRow(row, index, $event)"
Expand All @@ -305,7 +306,7 @@
v-for="(column, colindex) in visibleColumns"
:key="column.newKey + ':' + index + ':' + colindex"
>
<template v-if="column.$scopedSlots && column.$scopedSlots.default">
<template v-if="column.$slots.default">
<b-slot-component
:component="column"
v-bind="column.tdAttrs(row, column)"
Expand All @@ -327,7 +328,7 @@
>
<b-checkbox
autocomplete="off"
:value="isRowChecked(row)"
:model-value="isRowChecked(row)"
:type="checkboxType"
:disabled="!isRowCheckable(row)"
@click.prevent.stop="checkRow(row, index, $event)"
Expand Down Expand Up @@ -419,7 +420,7 @@
</template>

<script>
import { getValueByPath, indexOf, multiColumnSort, escapeRegExpChars, toCssWidth, removeDiacriticsFromString, isNil } from '../../utils/helpers'
import { getValueByPath, indexOf, multiColumnSort, escapeRegExpChars, toCssWidth, removeDiacriticsFromString, isFragment, isNil } from '../../utils/helpers'
import debounce from '../../utils/debounce'
import Checkbox from '../checkbox/Checkbox.vue'
import Icon from '../icon/Icon.vue'
Expand Down Expand Up @@ -752,7 +753,7 @@ export default {
hasCustomSubheadings() {
if (this.$slots && this.$slots.subheading) return true
return this.newColumns.some((column) => {
return column.subheading || (column.$scopedSlots && column.$scopedSlots.subheading)
return column.subheading || column.$slots.subheading
})
},
Expand Down Expand Up @@ -793,11 +794,6 @@ export default {
})
}
return this.defaultSlots
.filter((vnode) =>
vnode.componentInstance &&
vnode.componentInstance.$data &&
vnode.componentInstance.$data._isTableColumn)
.map((vnode) => vnode.componentInstance)
},
canDragRow() {
return this.draggable && !this.isDraggingColumn
Expand Down Expand Up @@ -1279,9 +1275,14 @@ export default {
* Assumes that `$slots.footer` is specified.
*/
hasCustomFooterSlot() {
if (this.$slots.footer().length > 1) return true
const footer = this.$slots.footer()
if (footer.length > 1) return true
// if a template is specified to `footer`, `footer.length` is 1
// but should contain multiple elements.
if (isFragment(footer[0])) return true
const tag = this.$slots.footer()[0].tag
const tag = footer[0].tag
if (tag !== 'th' && tag !== 'td') return false
return true
Expand Down Expand Up @@ -1454,12 +1455,19 @@ export default {
this.$emit('columndragleave', { event, column, index })
},
refreshSlots() {
this.defaultSlots = this.$slots.default || []
_registerTableColumn(column) {
if (column._isTableColumn) {
this.defaultSlots.push(column)
}
},
_unregisterTableColumn(column) {
const index = this.defaultSlots.indexOf(column)
if (index !== -1) {
this.defaultSlots.splice(index, 1)
}
}
},
mounted() {
this.refreshSlots()
this.checkPredefinedDetailedRows()
this.checkSort()
}
Expand Down
5 changes: 2 additions & 3 deletions src/components/table/TableColumn.vue
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,12 @@ export default {
},
created() {
if (!this.$table) {
this.$destroy()
throw new Error('You should wrap bTableColumn on a bTable')
}
this.$table.refreshSlots()
this.$table._registerTableColumn(this)
},
beforeUnmount() {
this.$table.refreshSlots()
this.$table._unregisterTableColumn(this)
},
render(createElement) {
// renderless
Expand Down
39 changes: 32 additions & 7 deletions src/components/table/TableMobileSort.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<div class="field table-mobile-sort">
<div class="field has-addons">
<b-select
v-model="sortMultipleSelect"
v-model="sortMultipleSelectIndex"
expanded
v-if="sortMultiple"
>
<option
v-for="(column, index) in sortableColumns"
:key="index"
:value="column"
:value="index"
>
{{ getLabel(column) }}
<template v-if="getSortingObjectOfColumn(column)">
Expand All @@ -23,7 +23,7 @@
</option>
</b-select>
<b-select
v-model="mobileSort"
v-model="mobileSortIndex"
expanded
v-else
>
Expand All @@ -41,7 +41,7 @@
<option
v-for="(column, index) in sortableColumns"
:key="index"
:value="column"
:value="index"
>
{{ column.label }}
</option>
Expand Down Expand Up @@ -125,7 +125,9 @@ export default {
data() {
return {
sortMultipleSelect: '',
sortMultipleSelectIndex: -1,
mobileSort: this.currentSortColumn,
mobileSortIndex: this.columns.indexOf(this.currentSortColumn),
defaultEvent: {
shiftKey: true,
altKey: true,
Expand All @@ -150,13 +152,36 @@ export default {
this.$emit('sort', column, this.defaultEvent)
}
},
sortMultipleSelectIndex(index) {
if (index !== -1) {
this.sortMultipleSelect = this.columns[index]
} else {
this.sortMultipleSelect = null
}
},
mobileSort(column) {
if (this.currentSortColumn === column) return
this.$emit('sort', column, this.defaultEvent)
},
mobileSortIndex(index) {
if (index !== -1) {
this.mobileSort = this.columns[index]
} else {
this.mobileSort = null
}
},
currentSortColumn(column) {
this.mobileSort = column
this.mobileSortIndex = this.columns.indexOf(column)
},
columns(newColumns) {
if (this.sortMultiple) {
this.sortMultipleSelectIndex = newColumns.indexOf(
this.sortMultipleSelect
)
} else {
this.mobileSortIndex = newColumns.indexOf(this.mobileSort)
}
}
},
methods: {
Expand All @@ -170,8 +195,8 @@ export default {
const remainingFields = this.sortMultipleData.filter((data) =>
data.field !== this.sortMultipleSelect.field)
.map((data) => data.field)
this.sortMultipleSelect = this.columns.filter((column) =>
remainingFields.includes(column.field))[0]
this.sortMultipleSelectIndex = this.columns.findIndex((column) =>
remainingFields.includes(column.field))
},
getSortingObjectOfColumn(column) {
return this.sortMultipleData.filter((i) =>
Expand Down
2 changes: 1 addition & 1 deletion src/components/table/mockTableColumn.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default function mockTableColumn(table, column) {
$emit: (...args) => eventEmitter.emit(...args),
// special fields
_isVue: true,
$scopedSlots: {
$slots: {
default: (props) => {
const vnode = createElement('span', {
innerHTML: getValueByPath(props.row, column.field)
Expand Down
10 changes: 4 additions & 6 deletions src/utils/SlotComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,9 @@ export default {
}
},
render() {
if (isVueComponent(this.component)) {
return createElement(this.tag, {},
this.scoped
? this.component.$scopedSlots[this.name](this.props)
: this.component.$slots[this.name])
}
return createElement(this.tag, {},
this.scoped
? this.component.$slots[this.name](this.props)
: this.component.$slots[this.name]())
}
}

0 comments on commit 34e4f7a

Please sign in to comment.