From 42a1ef2a665d0d2b13039b57bd1b4988d4d3fefe Mon Sep 17 00:00:00 2001 From: cagataycivici Date: Sun, 19 Apr 2020 12:09:27 +0300 Subject: [PATCH] Fixed #279 - filterLocale for components with filtering --- src/components/datatable/DataTable.d.ts | 1 + src/components/datatable/DataTable.vue | 8 +++-- src/components/dropdown/Dropdown.d.ts | 1 + src/components/dropdown/Dropdown.vue | 9 +++--- src/components/listbox/Listbox.d.ts | 1 + src/components/listbox/Listbox.vue | 5 +-- src/components/multiselect/MultiSelect.d.ts | 1 + src/components/multiselect/MultiSelect.vue | 3 +- src/components/tree/Tree.d.ts | 1 + src/components/tree/Tree.vue | 8 +++-- src/components/treetable/TreeTable.d.ts | 1 + src/components/treetable/TreeTable.vue | 8 +++-- src/components/utils/FilterUtils.js | 36 ++++++++++----------- src/views/datatable/DataTableDoc.vue | 6 ++++ src/views/dropdown/DropdownDoc.vue | 6 ++++ src/views/listbox/ListboxDoc.vue | 6 ++++ src/views/multiselect/MultiSelectDoc.vue | 6 ++++ src/views/tree/TreeDoc.vue | 6 ++++ src/views/treetable/TreeTableDoc.vue | 6 ++++ 19 files changed, 88 insertions(+), 31 deletions(-) diff --git a/src/components/datatable/DataTable.d.ts b/src/components/datatable/DataTable.d.ts index a0f2822be..39ea720b3 100644 --- a/src/components/datatable/DataTable.d.ts +++ b/src/components/datatable/DataTable.d.ts @@ -25,6 +25,7 @@ export declare class DataTable extends Vue { filters?: { [s: string]: any; }; + filterLocale?: string; selection?: any[]|any; selectionMode?: string; compareSelectionBy?: string; diff --git a/src/components/datatable/DataTable.vue b/src/components/datatable/DataTable.vue index 83021512c..a5cb224c0 100644 --- a/src/components/datatable/DataTable.vue +++ b/src/components/datatable/DataTable.vue @@ -230,6 +230,10 @@ export default { type: Object, default: null }, + filterLocale: { + type: String, + default: null + }, selection: { type: [Array,Object], default: null @@ -597,7 +601,7 @@ export default { let filterValue = this.filters[columnField]; let dataFieldValue = ObjectUtils.resolveFieldData(data[i], columnField); let filterConstraint = col.filterMatchMode === 'custom' ? col.filterFunction : FilterUtils[col.filterMatchMode]; - if (!filterConstraint(dataFieldValue, filterValue)) { + if (!filterConstraint(dataFieldValue, filterValue, this.filterLocale)) { localMatch = false; } @@ -607,7 +611,7 @@ export default { } if (!col.excludeGlobalFilter && this.hasGlobalFilter && !globalMatch) { - globalMatch = FilterUtils.contains(ObjectUtils.resolveFieldData(data[i], columnField), this.filters['global']); + globalMatch = FilterUtils.contains(ObjectUtils.resolveFieldData(data[i], columnField), this.filters['global'], this.filterLocale); } } diff --git a/src/components/dropdown/Dropdown.d.ts b/src/components/dropdown/Dropdown.d.ts index 8fd268587..63e9e968a 100644 --- a/src/components/dropdown/Dropdown.d.ts +++ b/src/components/dropdown/Dropdown.d.ts @@ -9,6 +9,7 @@ export declare class Dropdown extends Vue { scrollHeight?: string; filter?: boolean; filterPlaceholder?: string; + filterLocale?: string; editable?: boolean; placeholder?: string; disabled?: boolean; diff --git a/src/components/dropdown/Dropdown.vue b/src/components/dropdown/Dropdown.vue index 976727d18..210194586 100644 --- a/src/components/dropdown/Dropdown.vue +++ b/src/components/dropdown/Dropdown.vue @@ -52,7 +52,8 @@ export default { default: '200px' }, filter: Boolean, - filterPlaceholder: String, + filterPlaceholder: String, + filterLocale: String, editable: Boolean, placeholder: String, disabled: Boolean, @@ -378,8 +379,8 @@ export default { searchOptionInRange(start, end) { for (let i = start; i < end; i++) { let opt = this.visibleOptions[i]; - let label = this.getOptionLabel(opt).toLowerCase(); - if (label.startsWith(this.searchValue.toLowerCase())) { + let label = this.getOptionLabel(opt).toLocaleLowerCase(this.filterLocale); + if (label.startsWith(this.searchValue.toLocaleLowerCase(this.filterLocale))) { return opt; } } @@ -406,7 +407,7 @@ export default { computed: { visibleOptions() { if (this.filterValue && this.filterValue.trim().length > 0) - return this.options.filter(option => this.getOptionLabel(option).toLowerCase().indexOf(this.filterValue.toLowerCase()) > -1); + return this.options.filter(option => this.getOptionLabel(option).toLocaleLowerCase(this.filterLocale).indexOf(this.filterValue.toLocaleLowerCase(this.filterLocale)) > -1); else return this.options; }, diff --git a/src/components/listbox/Listbox.d.ts b/src/components/listbox/Listbox.d.ts index b9413d8b6..17bcb5096 100644 --- a/src/components/listbox/Listbox.d.ts +++ b/src/components/listbox/Listbox.d.ts @@ -12,6 +12,7 @@ export declare class Listbox extends Vue { multiple?: boolean; metaKeySelection?: boolean; filter?: boolean; + filterLocale?: string; ariaLabelledBy?: string; $emit(eventName: 'input', value: any): this; $emit(eventName: 'change', e: { originalEvent: Event, value: any }): this; diff --git a/src/components/listbox/Listbox.vue b/src/components/listbox/Listbox.vue index 7a9da051b..4c6611ac9 100644 --- a/src/components/listbox/Listbox.vue +++ b/src/components/listbox/Listbox.vue @@ -35,7 +35,8 @@ export default { dataKey: null, multiple: Boolean, metaKeySelection: Boolean, - filter: Boolean + filter: Boolean, + filterLocale: String }, optionTouched: false, data() { @@ -218,7 +219,7 @@ export default { computed: { visibleOptions() { if (this.filterValue) - return this.options.filter(option => this.getOptionLabel(option).toLowerCase().indexOf(this.filterValue.toLowerCase()) > -1); + return this.options.filter(option => this.getOptionLabel(option).toLocaleLowerCase(this.filterLocale).indexOf(this.filterValue.toLocaleLowerCase(this.filterLocale)) > -1); else return this.options; }, diff --git a/src/components/multiselect/MultiSelect.d.ts b/src/components/multiselect/MultiSelect.d.ts index 289d723e5..38bfe0eeb 100644 --- a/src/components/multiselect/MultiSelect.d.ts +++ b/src/components/multiselect/MultiSelect.d.ts @@ -13,6 +13,7 @@ export declare class MultiSelect extends Vue { tabindex?: string; dataKey?: string; filterPlaceholder?: string; + filterLocale?: string; ariaLabelledBy?: string; appendTo?: string; $emit(eventName: 'input', value: any): this; diff --git a/src/components/multiselect/MultiSelect.vue b/src/components/multiselect/MultiSelect.vue index 9eac86771..470cc19e8 100644 --- a/src/components/multiselect/MultiSelect.vue +++ b/src/components/multiselect/MultiSelect.vue @@ -74,6 +74,7 @@ export default { tabindex: String, dataKey: null, filterPlaceholder: String, + filterLocale: String, ariaLabelledBy: null, appendTo: { type: String, @@ -340,7 +341,7 @@ export default { computed: { visibleOptions() { if (this.filterValue && this.filterValue.trim().length > 0) - return this.options.filter(option => this.getOptionLabel(option).toLowerCase().indexOf(this.filterValue.toLowerCase()) > -1); + return this.options.filter(option => this.getOptionLabel(option).toLocaleLowerCase(this.filterLocale).indexOf(this.filterValue.toLocaleLowerCase(this.filterLocale)) > -1); else return this.options; }, diff --git a/src/components/tree/Tree.d.ts b/src/components/tree/Tree.d.ts index d64a0a226..b24f6f8d4 100644 --- a/src/components/tree/Tree.d.ts +++ b/src/components/tree/Tree.d.ts @@ -12,6 +12,7 @@ export declare class Tree extends Vue { filterBy?: string; filterMode?: string; filterPlaceholder?: string; + filterLocale?: string; $emit(eventName: 'node-select', node: any): this; $emit(eventName: 'node-unselect', node: any): this; $emit(eventName: 'node-expand', node: any): this; diff --git a/src/components/tree/Tree.vue b/src/components/tree/Tree.vue index 2baa69de0..7acf871c8 100644 --- a/src/components/tree/Tree.vue +++ b/src/components/tree/Tree.vue @@ -68,6 +68,10 @@ export default { filterPlaceholder: { type: String, default: null + }, + filterLocale: { + type: String, + default: null } }, data() { @@ -221,7 +225,7 @@ export default { isFilterMatched(node, {searchFields, filterText, strict}) { let matched = false; for(let field of searchFields) { - let fieldValue = String(ObjectUtils.resolveFieldData(node, field)).toLowerCase(); + let fieldValue = String(ObjectUtils.resolveFieldData(node, field)).toLocaleLowerCase(this.filterLocale); if(fieldValue.indexOf(filterText) > -1) { matched = true; } @@ -247,7 +251,7 @@ export default { filteredValue() { let filteredNodes = []; const searchFields = this.filterBy.split(','); - const filterText = this.filterValue.trim().toLowerCase(); + const filterText = this.filterValue.trim().toLocaleLowerCase(this.filterLocale); const strict = this.filterMode === 'strict'; for (let node of this.value) { diff --git a/src/components/treetable/TreeTable.d.ts b/src/components/treetable/TreeTable.d.ts index be622dbce..590504ab4 100644 --- a/src/components/treetable/TreeTable.d.ts +++ b/src/components/treetable/TreeTable.d.ts @@ -31,6 +31,7 @@ export declare class TreeTable extends Vue { [s: string]: any; }; filterMode?: string; + filterLocale?: string; resizableColumns?: boolean; columnResizeMode?: string; $emit(eventName: 'page', event: Event): this; diff --git a/src/components/treetable/TreeTable.vue b/src/components/treetable/TreeTable.vue index 473a6f851..555797097 100644 --- a/src/components/treetable/TreeTable.vue +++ b/src/components/treetable/TreeTable.vue @@ -200,6 +200,10 @@ export default { type: String, default: 'lenient' }, + filterLocale: { + type: String, + default: null + }, resizableColumns: { type: Boolean, default: false @@ -590,7 +594,7 @@ export default { if (this.hasGlobalFilter && !globalMatch) { let copyNodeForGlobal = {...copyNode}; let globalFilterValue = this.props.globalFilter; - let globalFilterConstraint = ObjectUtils.filterConstraints['contains']; + let globalFilterConstraint = FilterUtils['contains']; let globalFilterParamsWithoutNode = {filterField, globalFilterValue, globalFilterConstraint, strict}; if ((strict && (this.findFilteredNodes(copyNodeForGlobal, globalFilterParamsWithoutNode) || this.isFilterMatched(copyNodeForGlobal, globalFilterParamsWithoutNode))) || @@ -642,7 +646,7 @@ export default { isFilterMatched(node, {filterField, filterValue, filterConstraint, strict}) { let matched = false; let dataFieldValue = ObjectUtils.resolveFieldData(node.data, filterField); - if (filterConstraint(dataFieldValue, filterValue)) { + if (filterConstraint(dataFieldValue, filterValue, this.filterLocale)) { matched = true; } diff --git a/src/components/utils/FilterUtils.js b/src/components/utils/FilterUtils.js index 56077a87a..10de63d60 100644 --- a/src/components/utils/FilterUtils.js +++ b/src/components/utils/FilterUtils.js @@ -2,7 +2,7 @@ import ObjectUtils from './ObjectUtils'; export default class FilterUtils { - static startsWith(value, filter) { + static startsWith(value, filter, filterLocale) { if (filter === undefined || filter === null || filter.trim() === '') { return true; } @@ -11,13 +11,13 @@ export default class FilterUtils { return false; } - let filterValue = ObjectUtils.removeAccents(filter.toString()).toLowerCase(); - let stringValue = ObjectUtils.removeAccents(value.toString()).toLowerCase(); + let filterValue = ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale); + let stringValue = ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale); return stringValue.slice(0, filterValue.length) === filterValue; } - static contains(value, filter) { + static contains(value, filter, filterLocale) { if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { return true; } @@ -26,13 +26,13 @@ export default class FilterUtils { return false; } - let filterValue = ObjectUtils.removeAccents(filter.toString()).toLowerCase(); - let stringValue = ObjectUtils.removeAccents(value.toString()).toLowerCase(); + let filterValue = ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale); + let stringValue = ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale); return stringValue.indexOf(filterValue) !== -1; } - static endsWith(value, filter) { + static endsWith(value, filter, filterLocale) { if (filter === undefined || filter === null || filter.trim() === '') { return true; } @@ -41,13 +41,13 @@ export default class FilterUtils { return false; } - let filterValue = ObjectUtils.removeAccents(filter.toString()).toLowerCase(); - let stringValue = ObjectUtils.removeAccents(value.toString()).toLowerCase(); + let filterValue = ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale); + let stringValue = ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale); return stringValue.indexOf(filterValue, stringValue.length - filterValue.length) !== -1; } - static equals(value, filter) { + static equals(value, filter, filterLocale) { if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { return true; } @@ -59,10 +59,10 @@ export default class FilterUtils { if (value.getTime && filter.getTime) return value.getTime() === filter.getTime(); else - return ObjectUtils.removeAccents(value.toString()).toLowerCase() === ObjectUtils.removeAccents(filter.toString()).toLowerCase(); + return ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale) === ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale); } - static notEquals(value, filter) { + static notEquals(value, filter, filterLocale) { if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { return false; } @@ -74,10 +74,10 @@ export default class FilterUtils { if (value.getTime && filter.getTime) return value.getTime() !== filter.getTime(); else - return ObjectUtils.removeAccents(value.toString()).toLowerCase() !== ObjectUtils.removeAccents(filter.toString()).toLowerCase(); + return ObjectUtils.removeAccents(value.toString()).toLocaleLowerCase(filterLocale) !== ObjectUtils.removeAccents(filter.toString()).toLocaleLowerCase(filterLocale); } - static in(value, filter) { + static in(value, filter, filterLocale) { if (filter === undefined || filter === null || filter.length === 0) { return true; } @@ -95,7 +95,7 @@ export default class FilterUtils { return false; } - static lt(value, filter) { + static lt(value, filter, filterLocale) { if (filter === undefined || filter === null || (filter.trim && filter.trim().length === 0)) { return true; } @@ -110,7 +110,7 @@ export default class FilterUtils { return value < parseFloat(filter); } - static lte(value, filter) { + static lte(value, filter, filterLocale) { if (filter === undefined || filter === null || (filter.trim && filter.trim().length === 0)) { return true; } @@ -125,7 +125,7 @@ export default class FilterUtils { return value <= parseFloat(filter); } - static gt(value, filter) { + static gt(value, filter, filterLocale) { if (filter === undefined || filter === null || (filter.trim && filter.trim().length === 0)) { return true; } @@ -140,7 +140,7 @@ export default class FilterUtils { return value > parseFloat(filter); } - static gte(value, filter) { + static gte(value, filter, filterLocale) { if (filter === undefined || filter === null || (filter.trim && filter.trim().length === 0)) { return true; } diff --git a/src/views/datatable/DataTableDoc.vue b/src/views/datatable/DataTableDoc.vue index d433ab65f..4c9e10646 100644 --- a/src/views/datatable/DataTableDoc.vue +++ b/src/views/datatable/DataTableDoc.vue @@ -1831,6 +1831,12 @@ export default { null Filters object with key-value pairs to define the filters. + + filterLocale + string + undefined + Locale to use in filtering. The default locale is the host environment's current locale. + selection any diff --git a/src/views/dropdown/DropdownDoc.vue b/src/views/dropdown/DropdownDoc.vue index c6ec8f479..5094c3b0e 100644 --- a/src/views/dropdown/DropdownDoc.vue +++ b/src/views/dropdown/DropdownDoc.vue @@ -124,6 +124,12 @@ data() { null Placeholder text to show when filter input is empty. + + filterLocale + string + undefined + Locale to use in filtering. The default locale is the host environment's current locale. + editable boolean diff --git a/src/views/listbox/ListboxDoc.vue b/src/views/listbox/ListboxDoc.vue index 77118035a..de208486a 100644 --- a/src/views/listbox/ListboxDoc.vue +++ b/src/views/listbox/ListboxDoc.vue @@ -136,6 +136,12 @@ data() { boolean false When specified, displays a filter input at header. + + + filterLocale + string + undefined + Locale to use in filtering. The default locale is the host environment's current locale. diff --git a/src/views/multiselect/MultiSelectDoc.vue b/src/views/multiselect/MultiSelectDoc.vue index 8a29ec4b3..92327e49b 100644 --- a/src/views/multiselect/MultiSelectDoc.vue +++ b/src/views/multiselect/MultiSelectDoc.vue @@ -148,6 +148,12 @@ data() { null Placeholder text to show when filter input is empty. + + filterLocale + string + undefined + Locale to use in filtering. The default locale is the host environment's current locale. + ariaLabelledBy string diff --git a/src/views/tree/TreeDoc.vue b/src/views/tree/TreeDoc.vue index aa5fc2ed0..e6e83cead 100644 --- a/src/views/tree/TreeDoc.vue +++ b/src/views/tree/TreeDoc.vue @@ -622,6 +622,12 @@ export default { string null Placeholder text to show when filter input is empty. + + + filterLocale + string + undefined + Locale to use in filtering. The default locale is the host environment's current locale. diff --git a/src/views/treetable/TreeTableDoc.vue b/src/views/treetable/TreeTableDoc.vue index cbfc0462a..9a7dc78b1 100644 --- a/src/views/treetable/TreeTableDoc.vue +++ b/src/views/treetable/TreeTableDoc.vue @@ -1411,6 +1411,12 @@ export default { lenient Mode for filtering valid values are "lenient" and "strict". Default is lenient. + + filterLocale + string + undefined + Locale to use in filtering. The default locale is the host environment's current locale. + resizableColumns boolean