UNPKG

gridjs-vue

Version:

A Vue.js wrapper component for Grid.js

253 lines (240 loc) 5.94 kB
import { Grid } from 'https://unpkg.com/gridjs@5.0.1/dist/gridjs.module.js' import parseStylesheet from 'https://unpkg.com/parse-css-stylesheet/index.js' import { uid } from 'https://unpkg.com/uid/single/index.mjs' const waitForSelector = selector => { const element = document.querySelector(selector) if (element) return element const mutObserver = new MutationObserver(mutations => { for (const mutation of mutations) { const nodes = Array.from(mutation.addedNodes) for (const node of nodes) { if (node.matches && node.matches(selector)) { mutObserver.disconnect() return node } } } }) mutObserver.observe(document.documentElement, { childList: true, subtree: true }) } export default { name: 'Grid', props: { autoWidth: { type: Boolean, default: true }, classNames: { type: Object, default: undefined }, cols: { type: [Array, Function], default: undefined }, from: { type: [String, Function], default: undefined }, language: { type: Object, default: undefined }, pagination: { type: [Object, Boolean], default: false }, rows: { type: [Array, Function], default: undefined }, search: { type: [Object, Boolean], default: false }, server: { type: [Object, Function], default: undefined }, sort: { type: [Object, Boolean], default: false }, styles: { type: Object, default: undefined }, theme: { type: String, default: undefined }, width: { type: String, default: '100%' } }, data() { return { dict: { error: { columnsUndefined: 'Column headers are undefined', rowsUndefined: 'No data to display' } }, grid: null, uuid: null, wrapper: null } }, computed: { tabularData() { if (this.rows) return this.rows if (this.from || this.server) return undefined return [[this.dict.error.rowsUndefined]] }, options() { let options = { autoWidth: this.autoWidth, columns: this.cols ? this.cols : [this.dict.error.columnsUndefined], data: this.tabularData, pagination: this.pagination, sort: this.sort, width: this.width } if (this.classNames) options.className = this.classNames if (this.from) options.from = typeof this.from === 'string' ? document.querySelector(this.from) : document.createRange().createContextualFragment(this.from()) if (this.language) options.language = this.language if (this.search) options.search = this.search if (this.server) options.server = this.server if (this.styles) options.style = this.styles return options }, activeTheme() { if (this.theme) return this.theme if (this.$gridjs.options.theme) return this.$gridjs.options.theme return 'mermaid' }, divId() { return `gridjs__${this.uuid}` } }, watch: { autoWidth() { this.update() }, classNames() { this.update() }, cols() { this.update() }, from() { this.update() }, language() { this.update() }, pagination() { this.update() }, rows() { this.update() }, search() { this.update() }, server() { this.update() }, sort() { this.update() }, styles() { this.update() }, theme() { this.update() }, width() { this.update() } }, async created() { try { // give table a unique id this.uuid = uid(16) // get the wrapper await waitForSelector(this.divId) this.wrapper = document.getElementById(this.divId) // instantiate grid.js if (Object.keys(this.$gridjs.options).length) this.setOptions() if (this.wrapper && (this.options.data || this.options.from || this.options.server)) { this.grid = new Grid(this.options).render(this.wrapper) } } catch (error) { console.error(error) } }, mounted() { this.assignTheme() }, destroyed() { // unload from memory this.grid = undefined this.wrapper = undefined }, methods: { async assignTheme() { try { if (this.activeTheme !== 'none') { const head = document.getElementsByTagName('head')[0] let styles = document.createElement('style') styles.title = `${this.divId}__theme` styles.type = 'text/css' head.appendChild(styles) let theme = await fetch(`https://unpkg.com/gridjs/dist/theme/${this.activeTheme}.css`) theme = parseStylesheet(await theme.text()) for (let index in document.styleSheets) { if (document.styleSheets[index].title === styles.title) { styles = document.styleSheets[index] } } for (const index in theme.cssRules) { let css = theme.cssRules[index].cssText if (css && !/^@/g.test(css)) { styles.insertRule(`#${this.divId} ${css}`) } } } } catch (error) { console.error(error) } }, setOptions() { try { const plugins = this.$gridjs.options.plugins if (plugins) { plugins.forEach(plugin => { this.grid.plugin.add(plugin) }) } } catch (error) { console.error(error) } }, update() { try { if (this.grid) this.grid.updateConfig(this.options).forceRender() } catch (error) { console.error(error) } } }, template: ` <article :id="divId" :data-uuid="uuid" class="gridjs__wrapper"></article> ` }