quasar
Version:
Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time
275 lines (226 loc) • 6.49 kB
JavaScript
import Vue from 'vue'
import Top from './table-top.js'
import TableHeader from './table-header.js'
import TableBody from './table-body.js'
import Bottom from './table-bottom.js'
import TableGrid from './table-grid.js'
import QVirtualScroll from '../virtual-scroll/QVirtualScroll.js'
import { commonVirtPropsList } from '../../mixins/virtual-scroll.js'
import getTableMiddle from './get-table-middle.js'
import Sort from './table-sort.js'
import Filter from './table-filter.js'
import Pagination from './table-pagination.js'
import RowSelection from './table-row-selection.js'
import ColumnSelection from './table-column-selection.js'
import FullscreenMixin from '../../mixins/fullscreen.js'
const commonVirtPropsObj = {}
commonVirtPropsList.forEach(p => { commonVirtPropsObj[p] = {} })
export default Vue.extend({
name: 'QTable',
mixins: [
FullscreenMixin,
Top,
TableHeader,
TableBody,
Bottom,
TableGrid,
Sort,
Filter,
Pagination,
RowSelection,
ColumnSelection
],
props: {
data: {
type: Array,
default: () => []
},
rowKey: {
type: String,
default: 'id'
},
columns: Array,
loading: Boolean,
binaryStateSort: Boolean,
title: String,
hideHeader: Boolean,
hideBottom: Boolean,
grid: Boolean,
gridHeader: Boolean,
dense: Boolean,
flat: Boolean,
bordered: Boolean,
square: Boolean,
separator: {
type: String,
default: 'horizontal',
validator: v => ['horizontal', 'vertical', 'cell', 'none'].includes(v)
},
wrapCells: Boolean,
virtualScroll: Boolean,
...commonVirtPropsObj,
noDataLabel: String,
noResultsLabel: String,
loadingLabel: String,
selectedRowsLabel: Function,
rowsPerPageLabel: String,
paginationLabel: Function,
color: {
type: String,
default: 'grey-8'
},
tableStyle: [String, Array, Object],
tableClass: [String, Array, Object],
tableHeaderStyle: [String, Array, Object],
tableHeaderClass: [String, Array, Object],
cardStyle: [String, Array, Object],
cardClass: [String, Array, Object],
dark: Boolean
},
data () {
return {
rowsExpanded: {},
innerPagination: {
sortBy: null,
descending: false,
page: 1,
rowsPerPage: 5
}
}
},
watch: {
needsReset () {
this.hasVirtScroll === true && this.$refs.virtScroll.reset()
}
},
computed: {
hasVirtScroll () {
return this.grid !== true && this.virtualScroll === true
},
needsReset () {
return ['tableStyle', 'tableClass', 'tableHeaderStyle', 'tableHeaderClass', 'containerClass']
.map(p => this[p]).join(';')
},
computedData () {
let rows = this.data.slice().map((row, i) => {
row.__index = i
return row
})
if (rows.length === 0) {
return {
rowsNumber: 0,
rows: []
}
}
if (this.isServerSide === true) {
return { rows }
}
const { sortBy, descending, rowsPerPage } = this.computedPagination
if (this.filter) {
rows = this.filterMethod(rows, this.filter, this.computedCols, this.getCellValue)
}
if (this.columnToSort) {
rows = this.sortMethod(rows, sortBy, descending)
}
const rowsNumber = rows.length
if (rowsPerPage) {
rows = rows.slice(this.firstRowIndex, this.lastRowIndex)
}
return { rowsNumber, rows }
},
computedRows () {
return this.computedData.rows
},
computedRowsNumber () {
return this.isServerSide === true
? this.computedPagination.rowsNumber || 0
: this.computedData.rowsNumber
},
nothingToDisplay () {
return this.computedRows.length === 0
},
isServerSide () {
return this.computedPagination.rowsNumber !== void 0
},
cardDefaultClass () {
return ` q-table__card` +
(this.dark === true ? ' q-table__card--dark' : '') +
(this.square === true ? ` q-table--square` : '') +
(this.flat === true ? ` q-table--flat` : '') +
(this.bordered === true ? ` q-table--bordered` : '')
},
containerClass () {
return `q-table__container q-table--${this.separator}-separator` +
(this.grid === true ? ' q-table--grid' : this.cardDefaultClass) +
(this.dark === true ? ` q-table--dark` : '') +
(this.dense === true ? ` q-table--dense` : '') +
(this.wrapCells === false ? ` q-table--no-wrap` : '') +
(this.inFullscreen === true ? ` fullscreen scroll` : '')
},
virtProps () {
const props = {}
commonVirtPropsList
.forEach(p => { props[p] = this[p] })
if (props.virtualScrollItemSize === void 0) {
props.virtualScrollItemSize = this.dense === true ? 28 : 48
}
return props
}
},
render (h) {
const data = { staticClass: this.containerClass }
if (this.grid === false) {
data.class = this.cardClass
data.style = this.cardStyle
}
return h('div', data, [
this.getTop(h),
this.grid === true ? this.getGridHeader(h) : null,
this.getBody(h),
this.getBottom(h)
])
},
methods: {
requestServerInteraction (prop = {}) {
this.$nextTick(() => {
this.$emit('request', {
pagination: prop.pagination || this.computedPagination,
filter: prop.filter || this.filter,
getCellValue: this.getCellValue
})
})
},
resetVirtualScroll () {
this.hasVirtScroll === true && this.$refs.virtScroll.reset()
},
getBody (h) {
if (this.grid === true) {
return this.getGridBody(h)
}
const header = this.hideHeader !== true ? this.getTableHeader(h) : null
return this.hasVirtScroll === true
? h(QVirtualScroll, {
ref: 'virtScroll',
props: {
...this.virtProps,
items: this.computedRows,
type: '__qtable'
},
class: this.tableClass,
style: this.tableStyle,
scopedSlots: {
before: () => header,
default: this.getTableRowVirtual(h)
}
})
: getTableMiddle(h, {
staticClass: 'scroll',
class: this.tableClass,
style: this.tableStyle
}, [
header,
this.getTableBody(h)
])
}
}
})