Skip to content

Commit c1c055c

Browse files
authored
Create mixin-provider.js
1 parent 3993506 commit c1c055c

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import looseEqual from '../../../utils/loose-equal'
2+
import listenOnRootMixin from '../../../mixins/listen-on-root'
3+
4+
export default {
5+
mixins: [listenOnRootMixin],
6+
props: {
7+
noProviderPaging: {
8+
type: Boolean,
9+
default: false
10+
},
11+
noProviderSorting: {
12+
type: Boolean,
13+
default: false
14+
},
15+
noProviderFiltering: {
16+
type: Boolean,
17+
default: false
18+
},
19+
apiUrl: {
20+
// Passthrough prop. Passed to the context object. Not used by b-table directly
21+
type: String,
22+
default: ''
23+
}
24+
},
25+
computed: {
26+
hasProvider() {
27+
return this.items instanceof Function
28+
},
29+
providerTriggerContext() {
30+
// Used to trigger the provider function via a watcher. Only the fields that
31+
// are needed for triggering a provider update are included. Note that the
32+
// regular this.context is sent to the provider during fetches though, as they
33+
// may neeed all the prop info.
34+
const ctx = {
35+
apiUrl: this.apiUrl
36+
}
37+
if (!this.noProviderFiltering) {
38+
// Either a string, or could be an object or array.
39+
ctx.filter = this.localFilter
40+
}
41+
if (!this.noProviderSorting) {
42+
ctx.sortBy = this.localSortBy
43+
ctx.sortDesc = this.localSortDesc
44+
}
45+
if (!this.noProviderPaging) {
46+
ctx.perPage = this.perPage
47+
ctx.currentPage = this.currentPage
48+
}
49+
return ctx
50+
}
51+
},
52+
watch: {
53+
// Provider update triggering
54+
providerTriggerContext(newVal, oldVal) {
55+
// Trigger the provider to update as the relevant context values have changed.
56+
if (!looseEqual(newVal, oldVal)) {
57+
this.$nextTick(this._providerUpdate)
58+
}
59+
}
60+
},
61+
mounted() {
62+
// Call the items provider if necessary
63+
if (this.hasProvider && (!this.localItems || this.localItems.length === 0)) {
64+
// Fetch on mount if localItems is empty
65+
this._providerUpdate()
66+
}
67+
// Listen for global messages to tell us to force refresh the table
68+
this.listenOnRoot('bv::refresh::table', id => {
69+
if (id === this.id || id === this) {
70+
this.refresh()
71+
}
72+
})
73+
},
74+
methods: {
75+
refresh() {
76+
// Public Method: Force a refresh of the provider function
77+
this.$off('refreshed', this.refresh)
78+
if (this.computedBusy) {
79+
// Can't force an update when forced busy by user (busy prop === true)
80+
if (this.localBusy && this.hasProvider) {
81+
// But if provider running (localBusy), re-schedule refresh once `refreshed` emitted
82+
this.$on('refreshed', this.refresh)
83+
}
84+
} else {
85+
this.clearSelected()
86+
if (this.hasProvider) {
87+
this.$nextTick(this._providerUpdate)
88+
} else {
89+
/* istanbul ignore next */
90+
this.localItems = isArray(this.items) ? this.items.slice() : []
91+
}
92+
}
93+
},
94+
// Provider related methods
95+
_providerSetLocal(items) {
96+
this.localItems = isArray(items) ? items.slice() : []
97+
this.localBusy = false
98+
this.$emit('refreshed')
99+
// New root emit
100+
if (this.id) {
101+
this.emitOnRoot('bv::table::refreshed', this.id)
102+
}
103+
},
104+
_providerUpdate() {
105+
// Refresh the provider function items.
106+
if (!this.hasProvider) {
107+
// Do nothing if no provider
108+
return
109+
}
110+
// If table is busy, wait until refereshed before calling again
111+
if (this.computedBusy) {
112+
// Schedule a new refresh once `refreshed` is emitted
113+
this.$nextTick(this.refresh)
114+
return
115+
}
116+
117+
// Set internal busy state
118+
this.localBusy = true
119+
120+
// Call provider function with context and optional callback after DOM is fully updated
121+
this.$nextTick(function() {
122+
try {
123+
// Call provider function passing it the context and optional callback
124+
const data = this.items(this.context, this._providerSetLocal)
125+
if (data && data.then && typeof data.then === 'function') {
126+
// Provider returned Promise
127+
data.then(items => {
128+
// Provider resolved with items
129+
this._providerSetLocal(items)
130+
})
131+
} else if (isArray(data)) {
132+
// Provider returned Array data
133+
this._providerSetLocal(data)
134+
} else if (this.items.length !== 2) {
135+
// Check number of arguments provider function requested
136+
// Provider not using callback (didn't request second argument), so we clear
137+
// busy state as most likely there was an error in the provider function
138+
/* istanbul ignore next */
139+
warn(
140+
"b-table provider function didn't request calback and did not return a promise or data"
141+
)
142+
/* istanbul ignore next */
143+
this.localBusy = false
144+
}
145+
} catch (e) /* istanbul ignore next */ {
146+
// Provider function borked on us, so we spew out a warning
147+
// and clear the busy state
148+
warn(`b-table provider function error [${e.name}] ${e.message}`)
149+
this.localBusy = false
150+
this.$off('refreshed', this.refresh)
151+
}
152+
})
153+
}
154+
}
155+
}

0 commit comments

Comments
 (0)