Skip to content
Permalink
Browse files

fix(tables): fix issue with sticky columns when table is not responsi…

…ve but has sticky headers (fixes #4354) (#4356)
  • Loading branch information
tmorehouse committed Nov 8, 2019
1 parent 677de40 commit 56b395899ed9c6606e5757a2fd222a8c9aecf362
@@ -89,10 +89,12 @@ export default {
const hasDetailsSlot = this.hasNormalizedSlot(detailsSlotName)
const formatted = this.getFormattedValue(item, field)
const key = field.key
const stickyColumn =
!this.isStacked && (this.isResponsive || this.stickyHeader) && field.stickyColumn
// We only uses the helper components for sticky columns to
// improve performance of BTable/BTableLite by reducing the
// total number of vue instances created during render
const cellTag = field.stickyColumn
const cellTag = stickyColumn
? field.isRowHeader
? BTh
: BTd
@@ -118,11 +120,11 @@ export default {
: this.getTdValues(item, key, field.tdAttr, {}))
}
}
if (field.stickyColumn) {
if (stickyColumn) {
// We are using the helper BTd or BTh
data.props = {
stackedHeading: this.isStacked ? field.label : null,
stickyColumn: field.stickyColumn,
stickyColumn: true,
variant: cellVariant
}
} else {
@@ -11,10 +11,11 @@ const fields = [
]

describe('table > sticky columns', () => {
it('has expected classes when sticky column is enabled', async () => {
it('has expected classes when sticky column is enabled and responsive', async () => {
const wrapper = mount(BTable, {
propsData: {
responsive: true,
footClone: true,
items: items,
fields: fields
}
@@ -24,14 +25,102 @@ describe('table > sticky columns', () => {
expect(wrapper.is(BTable)).toBe(true)
expect(wrapper.is('div')).toBe(true)
expect(wrapper.classes()).toContain('table-responsive')
expect(wrapper.classes()).not.toContain('b-table-sticky-header')
const table = wrapper.find('table')
expect(table.classes()).toContain('table')
expect(table.classes()).toContain('b-table')

const trs = wrapper.findAll('tbody > tr')
// Body
let trs = wrapper.findAll('tbody > tr')
expect(trs.length).toBe(2)
let cells = trs.at(0).findAll('th, td')
expect(cells.length).toBe(3)

// First column should be BTh with sticky classes
expect(cells.at(0).is(BTh)).toBe(true)
expect(cells.at(0).is('th')).toBe(true)
expect(cells.at(0).classes()).toContain('b-table-sticky-column')

// Second column should be BTd with sticky classes
expect(cells.at(1).is(BTd)).toBe(true)
expect(cells.at(1).is('td')).toBe(true)
expect(cells.at(1).classes()).toContain('b-table-sticky-column')

// Third column should be td
expect(cells.at(2).is(BTd)).toBe(false)
expect(cells.at(2).is(BTh)).toBe(false)
expect(cells.at(2).is('td')).toBe(true)
expect(cells.at(2).classes()).not.toContain('b-table-sticky-column')

// Header cells
trs = wrapper.findAll('thead > tr')
expect(trs.length).toBe(1)
cells = trs.at(0).findAll('th')
expect(cells.length).toBe(3)

// First column should be BTh with sticky classes
expect(cells.at(0).is(BTh)).toBe(true)
expect(cells.at(0).is('th')).toBe(true)
expect(cells.at(0).classes()).toContain('b-table-sticky-column')

// Second column should be BTh with sticky classes
expect(cells.at(1).is(BTh)).toBe(true)
expect(cells.at(1).is('th')).toBe(true)
expect(cells.at(1).classes()).toContain('b-table-sticky-column')

// Third column should be BTh
expect(cells.at(2).is(BTh)).toBe(true)
expect(cells.at(2).is('th')).toBe(true)
expect(cells.at(2).classes()).not.toContain('b-table-sticky-column')

// Footer cells
trs = wrapper.findAll('tfoot > tr')
expect(trs.length).toBe(1)
cells = trs.at(0).findAll('th')
expect(cells.length).toBe(3)

// First column should be BTh with sticky classes
expect(cells.at(0).is(BTh)).toBe(true)
expect(cells.at(0).is('th')).toBe(true)
expect(cells.at(0).classes()).toContain('b-table-sticky-column')

// Second column should be BTh with sticky classes
expect(cells.at(1).is(BTh)).toBe(true)
expect(cells.at(1).is('th')).toBe(true)
expect(cells.at(1).classes()).toContain('b-table-sticky-column')

// Third column should be BTh
expect(cells.at(2).is(BTh)).toBe(true)
expect(cells.at(2).is('th')).toBe(true)
expect(cells.at(2).classes()).not.toContain('b-table-sticky-column')

const cells = trs.at(0).findAll('th, td')
wrapper.destroy()
})

it('has expected classes when sticky column is enabled with sticky headers', async () => {
const wrapper = mount(BTable, {
propsData: {
responsive: false,
stickyHeader: true,
footClone: true,
items: items,
fields: fields
}
})

expect(wrapper).toBeDefined()
expect(wrapper.is(BTable)).toBe(true)
expect(wrapper.is('div')).toBe(true)
expect(wrapper.classes()).not.toContain('table-responsive')
expect(wrapper.classes()).toContain('b-table-sticky-header')
const table = wrapper.find('table')
expect(table.classes()).toContain('table')
expect(table.classes()).toContain('b-table')

// Tbody cells
let trs = wrapper.findAll('tbody > tr')
expect(trs.length).toBe(2)
let cells = trs.at(0).findAll('th, td')
expect(cells.length).toBe(3)

// First column should be BTh with sticky classes
@@ -50,6 +139,134 @@ describe('table > sticky columns', () => {
expect(cells.at(2).is('td')).toBe(true)
expect(cells.at(2).classes()).not.toContain('b-table-sticky-column')

// Header cells
trs = wrapper.findAll('thead > tr')
expect(trs.length).toBe(1)
cells = trs.at(0).findAll('th')
expect(cells.length).toBe(3)

// First column should be BTh with sticky classes
expect(cells.at(0).is(BTh)).toBe(true)
expect(cells.at(0).is('th')).toBe(true)
expect(cells.at(0).classes()).toContain('b-table-sticky-column')

// Second column should be BTh with sticky classes
expect(cells.at(1).is(BTh)).toBe(true)
expect(cells.at(1).is('th')).toBe(true)
expect(cells.at(1).classes()).toContain('b-table-sticky-column')

// Third column should be BTh
expect(cells.at(2).is(BTh)).toBe(true)
expect(cells.at(2).is('th')).toBe(true)
expect(cells.at(2).classes()).not.toContain('b-table-sticky-column')

// Footer cells
trs = wrapper.findAll('tfoot > tr')
expect(trs.length).toBe(1)

cells = trs.at(0).findAll('th')
expect(cells.length).toBe(3)

// First column should be BTh with sticky classes
expect(cells.at(0).is(BTh)).toBe(true)
expect(cells.at(0).is('th')).toBe(true)
expect(cells.at(0).classes()).toContain('b-table-sticky-column')

// Second column should be BTh with sticky classes
expect(cells.at(1).is(BTh)).toBe(true)
expect(cells.at(1).is('th')).toBe(true)
expect(cells.at(1).classes()).toContain('b-table-sticky-column')

// Third column should be BTh
expect(cells.at(2).is(BTh)).toBe(true)
expect(cells.at(2).is('th')).toBe(true)
expect(cells.at(2).classes()).not.toContain('b-table-sticky-column')

wrapper.destroy()
})

it('does not have sticky classes when sticky column is enabled and not responsive and no sticky header', async () => {
const wrapper = mount(BTable, {
propsData: {
responsive: false,
stickyHeader: false,
footClone: true,
items: items,
fields: fields
}
})

expect(wrapper).toBeDefined()
expect(wrapper.is(BTable)).toBe(true)
expect(wrapper.is('table')).toBe(true)
expect(wrapper.classes()).not.toContain('table-responsive')
expect(wrapper.classes()).not.toContain('b-table-sticky-header')
expect(wrapper.classes()).toContain('table')
expect(wrapper.classes()).toContain('b-table')

// Body
let trs = wrapper.findAll('tbody > tr')
expect(trs.length).toBe(2)
let cells = trs.at(0).findAll('th, td')
expect(cells.length).toBe(3)

// First column should be th
expect(cells.at(0).is(BTh)).toBe(false)
expect(cells.at(0).is('th')).toBe(true)
expect(cells.at(0).classes()).not.toContain('b-table-sticky-column')

// Second column should be td
expect(cells.at(1).is(BTd)).toBe(false)
expect(cells.at(1).is('td')).toBe(true)
expect(cells.at(1).classes()).not.toContain('b-table-sticky-column')

// Third column should be td
expect(cells.at(2).is(BTd)).toBe(false)
expect(cells.at(2).is('td')).toBe(true)
expect(cells.at(2).classes()).not.toContain('b-table-sticky-column')

// Header cells
trs = wrapper.findAll('thead > tr')
expect(trs.length).toBe(1)
cells = trs.at(0).findAll('th')
expect(cells.length).toBe(3)

// First column should be BTh with sticky classes
expect(cells.at(0).is(BTh)).toBe(true)
expect(cells.at(0).is('th')).toBe(true)
expect(cells.at(0).classes()).not.toContain('b-table-sticky-column')

// Second column should be BTh with sticky classes
expect(cells.at(1).is(BTh)).toBe(true)
expect(cells.at(1).is('th')).toBe(true)
expect(cells.at(1).classes()).not.toContain('b-table-sticky-column')

// Third column should be BTh
expect(cells.at(2).is(BTh)).toBe(true)
expect(cells.at(2).is('th')).toBe(true)
expect(cells.at(2).classes()).not.toContain('b-table-sticky-column')

// Footer cells
trs = wrapper.findAll('tfoot > tr')
expect(trs.length).toBe(1)
cells = trs.at(0).findAll('th')
expect(cells.length).toBe(3)

// First column should be BTh with sticky classes
expect(cells.at(0).is(BTh)).toBe(true)
expect(cells.at(0).is('th')).toBe(true)
expect(cells.at(0).classes()).not.toContain('b-table-sticky-column')

// Second column should be BTh with sticky classes
expect(cells.at(1).is(BTh)).toBe(true)
expect(cells.at(1).is('th')).toBe(true)
expect(cells.at(1).classes()).not.toContain('b-table-sticky-column')

// Third column should be BTh
expect(cells.at(2).is(BTh)).toBe(true)
expect(cells.at(2).is('th')).toBe(true)
expect(cells.at(2).classes()).not.toContain('b-table-sticky-column')

wrapper.destroy()
})
})
@@ -53,6 +53,12 @@ export const BTbody = /*#__PURE__*/ Vue.extend({
// Sticky headers are only supported in thead
return false
},
hasStickyHeader() {
// Sniffed by <b-tr> / <b-td> / <b-th>
// Needed to handle header background classes, due to lack of
// background color inheritance with Bootstrap v4 table CSS
return !this.isStacked && this.bvTable.stickyHeader
},
tableVariant() /* istanbul ignore next: Not currently sniffed in tests */ {
// Sniffed by <b-tr> / <b-td> / <b-th>
return this.bvTable.tableVariant
@@ -85,13 +85,18 @@ export const BTd = /*#__PURE__*/ Vue.extend({
// Sticky headers only apply to cells in table `thead`
return this.bvTableTr.isStickyHeader
},
isStickyColumn() {
hasStickyHeader() {
// Needed to handle header background classes, due to lack of
// background color inheritance with Bootstrap v4 table CSS
return this.bvTableTr.hasStickyHeader
},
isStickyColumn() {
// Needed to handle background classes, due to lack of
// background color inheritance with Bootstrap v4 table CSS
// Sticky column cells are only available in responsive
// mode (horizontal scrolling) or when sticky header mode
// Applies to cells in `thead`, `tbody` and `tfoot`
return !this.isStacked && (this.isResponsive || this.isStickyHeader) && this.stickyColumn
return !this.isStacked && (this.isResponsive || this.hasStickyHeader) && this.stickyColumn
},
rowVariant() {
return this.bvTableTr.variant
@@ -49,6 +49,12 @@ export const BTfoot = /*#__PURE__*/ Vue.extend({
// Sticky headers are only supported in thead
return false
},
hasStickyHeader() {
// Sniffed by <b-tr> / <b-td> / <b-th>
// Needed to handle header background classes, due to lack of
// background color inheritance with Bootstrap v4 table CSS
return !this.isStacked && this.bvTable.stickyHeader
},
tableVariant() /* istanbul ignore next: Not currently sniffed in tests */ {
// Sniffed by <b-tr> / <b-td> / <b-th>
return this.bvTable.tableVariant
@@ -52,6 +52,12 @@ export const BThead = /*#__PURE__*/ Vue.extend({
// Sticky headers only apply to cells in table `thead`
return !this.isStacked && this.bvTable.stickyHeader
},
hasStickyHeader() {
// Sniffed by <b-tr> / <b-td> / <b-th>
// Needed to handle header background classes, due to lack of
// background color inheritance with Bootstrap v4 table CSS
return !this.isStacked && this.bvTable.stickyHeader
},
tableVariant() {
// Sniffed by <b-tr> / <b-td> / <b-th>
return this.bvTable.tableVariant
@@ -59,6 +59,12 @@ export const BTr = /*#__PURE__*/ Vue.extend({
// Sticky headers are only supported in thead
return this.bvTableRowGroup.isStickyHeader
},
hasStickyHeader() {
// Sniffed by <b-tr> / <b-td> / <b-th>
// Needed to handle header background classes, due to lack of
// background color inheritance with Bootstrap v4 table CSS
return !this.isStacked && this.bvTableRowGroup.hasStickyHeader
},
tableVariant() {
// Sniffed by <b-td> / <b-th>
return this.bvTableRowGroup.tableVariant

0 comments on commit 56b3958

Please sign in to comment.
You can’t perform that action at this time.