Skip to content

Commit b7e764a

Browse files
committed
chore: fix warnings about accessing undefined fields in render
* introduce "safe-vue-instance" helper
1 parent 2d6660f commit b7e764a

File tree

17 files changed

+102
-45
lines changed

17 files changed

+102
-45
lines changed

src/components/calendar/calendar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ export const BCalendar = Vue.extend({
811811
{
812812
staticClass: 'b-calendar-header',
813813
class: { 'sr-only': this.hideHeader },
814-
attrs: { title: this.selectedDate ? this.labelSelectedDate || null : null }
814+
attrs: { title: this.selectedDate ? this.labelSelected || null : null }
815815
},
816816
[$header]
817817
)

src/components/form-spinbutton/form-spinbutton.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ export const BFormSpinbutton = /*#__PURE__*/ Vue.extend({
113113
}
114114
},
115115
computed: {
116+
required() {
117+
return false
118+
},
116119
spinId() {
117120
return this.safeId()
118121
},

src/components/form-textarea/form-textarea.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ export const BFormTextarea = /*#__PURE__*/ Vue.extend({
6767
}
6868
},
6969
computed: {
70+
type() {
71+
return null
72+
},
7073
computedStyle() {
7174
const styles = {
7275
// Setting `noResize` to true will disable the ability for the user to

src/components/table/helpers/mixin-empty.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import { htmlOrText } from '../../../utils/html'
99
import { isFunction } from '../../../utils/inspect'
1010
import { makeProp } from '../../../utils/props'
11+
import { safeVueInstance } from '../../../utils/safe-vue-instance'
1112
import { BTr } from '../tr'
1213
import { BTd } from '../td'
1314

@@ -28,14 +29,14 @@ export const emptyMixin = Vue.extend({
2829
props,
2930
methods: {
3031
renderEmpty() {
31-
const { computedItems: items } = this
32+
const { computedItems: items, computedBusy } = safeVueInstance(this)
3233
const h = this.$createElement
3334

3435
let $empty = h()
3536
if (
3637
this.showEmpty &&
3738
(!items || items.length === 0) &&
38-
!(this.computedBusy && this.hasNormalizedSlot(SLOT_NAME_TABLE_BUSY))
39+
!(computedBusy && this.hasNormalizedSlot(SLOT_NAME_TABLE_BUSY))
3940
) {
4041
const {
4142
computedFields: fields,

src/components/table/helpers/mixin-items.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { makeModelMixin } from '../../../utils/model'
1010
import { toInteger } from '../../../utils/number'
1111
import { clone, sortKeys } from '../../../utils/object'
1212
import { makeProp } from '../../../utils/props'
13+
import { safeVueInstance } from '../../../utils/safe-vue-instance'
1314
import { normalizeFields } from './normalize-fields'
1415

1516
// --- Constants ---
@@ -86,24 +87,26 @@ export const itemsMixin = Vue.extend({
8687
}, {})
8788
},
8889
computedItems() {
90+
const { paginatedItems, sortedItems, filteredItems, localItems } = safeVueInstance(this)
8991
// Fallback if various mixins not provided
9092
return (
91-
this.paginatedItems ||
92-
this.sortedItems ||
93-
this.filteredItems ||
94-
this.localItems ||
93+
paginatedItems ||
94+
sortedItems ||
95+
filteredItems ||
96+
localItems ||
9597
/* istanbul ignore next */
9698
[]
9799
).slice()
98100
},
99101
context() {
102+
const { perPage, currentPage } = safeVueInstance(this)
100103
// Current state of sorting, filtering and pagination props/values
101104
return {
102105
filter: this.localFilter,
103106
sortBy: this.localSortBy,
104107
sortDesc: this.localSortDesc,
105-
perPage: mathMax(toInteger(this.perPage, 0), 0),
106-
currentPage: mathMax(toInteger(this.currentPage, 0), 1),
108+
perPage: mathMax(toInteger(perPage, 0), 0),
109+
currentPage: mathMax(toInteger(currentPage, 0), 1),
107110
apiUrl: this.apiUrl
108111
}
109112
}

src/components/table/helpers/mixin-pagination.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { PROP_TYPE_NUMBER_STRING } from '../../../constants/props'
33
import { mathMax } from '../../../utils/math'
44
import { toInteger } from '../../../utils/number'
55
import { makeProp } from '../../../utils/props'
6+
import { safeVueInstance } from '../../../utils/safe-vue-instance'
67

78
// --- Props ---
89

@@ -21,7 +22,8 @@ export const paginationMixin = Vue.extend({
2122
return this.hasProvider ? !!this.noProviderPaging : true
2223
},
2324
paginatedItems() {
24-
let items = this.sortedItems || this.filteredItems || this.localItems || []
25+
const { sortedItems, filteredItems, localItems } = safeVueInstance(this)
26+
let items = sortedItems || filteredItems || localItems || []
2527
const currentPage = mathMax(toInteger(this.currentPage, 1), 1)
2628
const perPage = mathMax(toInteger(this.perPage, 0), 0)
2729
// Apply local pagination

src/components/table/helpers/mixin-provider.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { isArray, isFunction, isPromise } from '../../../utils/inspect'
1111
import { looseEqual } from '../../../utils/loose-equal'
1212
import { clone } from '../../../utils/object'
1313
import { makeProp } from '../../../utils/props'
14+
import { safeVueInstance } from '../../../utils/safe-vue-instance'
1415
import { warn } from '../../../utils/warn'
1516
import { listenOnRootMixin } from '../../../mixins/listen-on-root'
1617

@@ -100,11 +101,11 @@ export const providerMixin = Vue.extend({
100101
},
101102
methods: {
102103
refresh() {
103-
const { items, refresh } = this
104+
const { items, refresh, computedBusy } = safeVueInstance(this)
104105

105106
// Public Method: Force a refresh of the provider function
106107
this.$off(EVENT_NAME_REFRESHED, refresh)
107-
if (this.computedBusy) {
108+
if (computedBusy) {
108109
// Can't force an update when forced busy by user (busy prop === true)
109110
if (this.localBusy && this.hasProvider) {
110111
// But if provider running (localBusy), re-schedule refresh once `refreshed` emitted
@@ -137,7 +138,7 @@ export const providerMixin = Vue.extend({
137138
return
138139
}
139140
// If table is busy, wait until refreshed before calling again
140-
if (this.computedBusy) {
141+
if (safeVueInstance(this).computedBusy) {
141142
// Schedule a new refresh once `refreshed` is emitted
142143
this.$nextTick(this.refresh)
143144
return

src/components/table/helpers/mixin-sorting.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import { arrayIncludes } from '../../../utils/array'
1515
import { isFunction, isUndefinedOrNull } from '../../../utils/inspect'
1616
import { makeProp } from '../../../utils/props'
17+
import { safeVueInstance } from '../../../utils/safe-vue-instance'
1718
import { stableSort } from '../../../utils/stable-sort'
1819
import { trim } from '../../../utils/string'
1920
import { defaultSortCompare } from './default-sort-compare'
@@ -93,9 +94,11 @@ export const sortingMixin = Vue.extend({
9394
sortCompareLocale: locale,
9495
sortNullLast: nullLast,
9596
sortCompare,
96-
localSorting
97-
} = this
98-
const items = (this.filteredItems || this.localItems || []).slice()
97+
localSorting,
98+
filteredItems,
99+
localItems
100+
} = safeVueInstance(this)
101+
const items = (filteredItems || localItems || []).slice()
99102
const localeOptions = { ...this.sortCompareOptions, usage: 'sort' }
100103

101104
if (sortBy && localSorting) {

src/components/table/helpers/mixin-table-renderer.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import { identity } from '../../../utils/identity'
99
import { isBoolean } from '../../../utils/inspect'
1010
import { makeProp } from '../../../utils/props'
11+
import { safeVueInstance } from '../../../utils/safe-vue-instance'
1112
import { toString } from '../../../utils/string'
1213
import { attrsMixin } from '../../../mixins/attrs'
1314

@@ -49,6 +50,9 @@ export const tableRendererMixin = Vue.extend({
4950
inheritAttrs: false,
5051
props,
5152
computed: {
53+
isTableSimple() {
54+
return false
55+
},
5256
// Layout related computed props
5357
isResponsive() {
5458
const { responsive } = this
@@ -75,14 +79,19 @@ export const tableRendererMixin = Vue.extend({
7579
return isStickyHeader && !isBoolean(isStickyHeader) ? { maxHeight: isStickyHeader } : {}
7680
},
7781
tableClasses() {
78-
let { hover, tableVariant } = this
79-
hover = this.isTableSimple
80-
? hover
81-
: hover && this.computedItems.length > 0 && !this.computedBusy
82+
let {
83+
hover,
84+
tableVariant,
85+
selectableTableClasses,
86+
stackedTableClasses,
87+
tableClass,
88+
computedBusy
89+
} = safeVueInstance(this)
90+
hover = this.isTableSimple ? hover : hover && this.computedItems.length > 0 && !computedBusy
8291

8392
return [
8493
// User supplied classes
85-
this.tableClass,
94+
tableClass,
8695
// Styling classes
8796
{
8897
'table-striped': this.striped,
@@ -99,23 +108,24 @@ export const tableRendererMixin = Vue.extend({
99108
},
100109
tableVariant ? `${this.dark ? 'bg' : 'table'}-${tableVariant}` : '',
101110
// Stacked table classes
102-
this.stackedTableClasses,
111+
stackedTableClasses,
103112
// Selectable classes
104-
this.selectableTableClasses
113+
selectableTableClasses
105114
]
106115
},
107116
tableAttrs() {
108117
const {
109118
computedItems: items,
110119
filteredItems,
111120
computedFields: fields,
112-
selectableTableAttrs
113-
} = this
121+
selectableTableAttrs,
122+
computedBusy
123+
} = safeVueInstance(this)
114124

115125
const ariaAttrs = this.isTableSimple
116126
? {}
117127
: {
118-
'aria-busy': toString(this.computedBusy),
128+
'aria-busy': toString(computedBusy),
119129
'aria-colcount': toString(fields.length),
120130
// Preserve user supplied `aria-describedby`, if provided
121131
'aria-describedby':
@@ -149,7 +159,7 @@ export const tableRendererMixin = Vue.extend({
149159
renderThead,
150160
renderTbody,
151161
renderTfoot
152-
} = this
162+
} = safeVueInstance(this)
153163

154164
const $content = []
155165
if (this.isTableSimple) {

src/components/table/helpers/mixin-tbody-row.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { useParentMixin } from '../../../mixins/use-parent'
1414
import { get } from '../../../utils/get'
1515
import { isFunction, isString, isUndefinedOrNull } from '../../../utils/inspect'
1616
import { makeProp } from '../../../utils/props'
17+
import { safeVueInstance } from '../../../utils/safe-vue-instance'
1718
import { toString } from '../../../utils/string'
1819
import { BTr } from '../tr'
1920
import { BTd } from '../td'
@@ -160,7 +161,7 @@ export const tbodyRowMixin = Vue.extend({
160161
}
161162
// If table supports selectable mode, then add in the following scope
162163
// this.supportsSelectableRows will be undefined if mixin isn't loaded
163-
if (this.supportsSelectableRows) {
164+
if (safeVueInstance(this).supportsSelectableRows) {
164165
slotScope.rowSelected = this.isRowSelected(rowIndex)
165166
slotScope.selectRow = () => this.selectRow(rowIndex)
166167
slotScope.unselectRow = () => this.unselectRow(rowIndex)
@@ -193,13 +194,13 @@ export const tbodyRowMixin = Vue.extend({
193194
currentPage,
194195
perPage,
195196
tbodyTrClass,
196-
tbodyTrAttr
197-
} = this
197+
tbodyTrAttr,
198+
hasSelectableRowClick
199+
} = safeVueInstance(this)
198200
const h = this.$createElement
199201
const hasDetailsSlot = this.hasNormalizedSlot(SLOT_NAME_ROW_DETAILS)
200202
const rowShowDetails = item[FIELD_KEY_SHOW_DETAILS] && hasDetailsSlot
201-
const hasRowClickHandler =
202-
this.$listeners[EVENT_NAME_ROW_CLICKED] || this.hasSelectableRowClick
203+
const hasRowClickHandler = this.$listeners[EVENT_NAME_ROW_CLICKED] || hasSelectableRowClick
203204

204205
// We can return more than one TR if rowDetails enabled
205206
const $rows = []
@@ -232,8 +233,12 @@ export const tbodyRowMixin = Vue.extend({
232233
const rowId = primaryKeyValue ? this.safeId(`_row_${primaryKeyValue}`) : null
233234

234235
// Selectable classes and attributes
235-
const selectableClasses = this.selectableRowClasses ? this.selectableRowClasses(rowIndex) : {}
236-
const selectableAttrs = this.selectableRowAttrs ? this.selectableRowAttrs(rowIndex) : {}
236+
const selectableClasses = safeVueInstance(this).selectableRowClasses
237+
? this.selectableRowClasses(rowIndex)
238+
: {}
239+
const selectableAttrs = safeVueInstance(this).selectableRowAttrs
240+
? this.selectableRowAttrs(rowIndex)
241+
: {}
237242

238243
// Additional classes and attributes
239244
const userTrClasses = isFunction(tbodyTrClass) ? tbodyTrClass(item, 'row') : tbodyTrClass
@@ -282,7 +287,7 @@ export const tbodyRowMixin = Vue.extend({
282287
}
283288
// If table supports selectable mode, then add in the following scope
284289
// this.supportsSelectableRows will be undefined if mixin isn't loaded
285-
if (this.supportsSelectableRows) {
290+
if (safeVueInstance(this).supportsSelectableRows) {
286291
detailsScope.rowSelected = this.isRowSelected(rowIndex)
287292
detailsScope.selectRow = () => this.selectRow(rowIndex)
288293
detailsScope.unselectRow = () => this.unselectRow(rowIndex)

0 commit comments

Comments
 (0)