diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json index bb6383bcf9a..d1c2eca0bf8 100644 --- a/.bundlewatch.config.json +++ b/.bundlewatch.config.json @@ -34,27 +34,27 @@ }, { "path": "./dist/bootstrap-vue.js", - "maxSize": "230 kB" + "maxSize": "235 kB" }, { "path": "./dist/bootstrap-vue.min.js", - "maxSize": "100 kB" + "maxSize": "105 kB" }, { "path": "./dist/bootstrap-vue.common.js", - "maxSize": "305 kB" + "maxSize": "310 kB" }, { "path": "./dist/bootstrap-vue.common.min.js", - "maxSize": "190 kB" + "maxSize": "195 kB" }, { "path": "./dist/bootstrap-vue.esm.js", - "maxSize": "300 kB" + "maxSize": "310 kB" }, { "path": "./dist/bootstrap-vue.esm.min.js", - "maxSize": "190 kB" + "maxSize": "195 kB" }, { "path": "./dist/bootstrap-vue.css", diff --git a/src/components/table/helpers/sanitize-row.js b/src/components/table/helpers/sanitize-row.js index 7f7ba6f3a5a..2509c2765ac 100644 --- a/src/components/table/helpers/sanitize-row.js +++ b/src/components/table/helpers/sanitize-row.js @@ -1,32 +1,41 @@ -import { keys } from '../../../utils/object' -import { arrayIncludes } from '../../../utils/array' +import { arrayIncludes, isArray } from '../../../utils/array' import { isFunction } from '../../../utils/inspect' +import { clone, keys, pick } from '../../../utils/object' import { IGNORED_FIELD_KEYS } from './constants' // Return a copy of a row after all reserved fields have been filtered out -const sanitizeRow = (row, ignoreFields, includeFields, fieldsObj = {}) => - keys(row).reduce((obj, key) => { - // Ignore special fields that start with `_` - // Ignore fields in the `ignoreFields` array - // Include only fields in the `includeFields` array - if ( - !IGNORED_FIELD_KEYS[key] && - !(ignoreFields && ignoreFields.length > 0 && arrayIncludes(ignoreFields, key)) && - !(includeFields && includeFields.length > 0 && !arrayIncludes(includeFields, key)) - ) { - const f = fieldsObj[key] || {} - const val = row[key] - // `f.filterByFormatted` will either be a function or boolean - // `f.formater` will have already been noramlized into a function ref - const filterByFormatted = f.filterByFormatted - const formatter = isFunction(filterByFormatted) - ? /* istanbul ignore next */ filterByFormatted - : filterByFormatted - ? /* istanbul ignore next */ f.formatter - : null - obj[key] = isFunction(formatter) ? formatter(val, key, row) : val +const sanitizeRow = (row, ignoreFields, includeFields, fieldsObj = {}) => { + // We first need to format the row based on the field configurations + // This ensures that we add formatted values for keys that may not + // exist in the row itself + const formattedRow = keys(fieldsObj).reduce((result, key) => { + const field = fieldsObj[key] + const { filterByFormatted } = field + const formatter = isFunction(filterByFormatted) + ? /* istanbul ignore next */ filterByFormatted + : filterByFormatted + ? /* istanbul ignore next */ field.formatter + : null + + if (isFunction(formatter)) { + result[key] = formatter(row[key], key, row) } - return obj - }, {}) + + return result + }, clone(row)) + + // Determine the allowed keys: + // - Ignore special fields that start with `_` + // - Ignore fields in the `ignoreFields` array + // - Include only fields in the `includeFields` array + const allowedKeys = keys(formattedRow).filter( + key => + !IGNORED_FIELD_KEYS[key] && + !(isArray(ignoreFields) && arrayIncludes(ignoreFields, key)) && + !(isArray(includeFields) && !arrayIncludes(includeFields, key)) + ) + + return pick(formattedRow, allowedKeys) +} export default sanitizeRow diff --git a/src/components/table/table-filtering.spec.js b/src/components/table/table-filtering.spec.js index aefc1fa52fc..b125fb9cb94 100644 --- a/src/components/table/table-filtering.spec.js +++ b/src/components/table/table-filtering.spec.js @@ -207,6 +207,34 @@ describe('table > filtering', () => { wrapper.destroy() }) + it('should filter for formatted values for keys which are not present in row', async () => { + const wrapper = mount(BTable, { + propsData: { + items: [{ a: 'A', b: 'B' }], + fields: [ + { key: 'a' }, + { + key: 'b', + formatter: () => 'Foo', + filterByFormatted: true + }, + { + key: 'c', + formatter: () => 'Bar', + filterByFormatted: true + } + ], + filter: 'Bar' + } + }) + expect(wrapper).toBeDefined() + await waitNT(wrapper.vm) + + expect(wrapper.findAll('tbody > tr').length).toBe(1) + + wrapper.destroy() + }) + it('should show empty filtered message when no matches and show-empty=true', async () => { const wrapper = mount(BTable, { propsData: {