diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/editors/multipleSelectEditor.ts b/aurelia-slickgrid/src/aurelia-slickgrid/editors/multipleSelectEditor.ts index 7f59a8861..de87d70dc 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/editors/multipleSelectEditor.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/editors/multipleSelectEditor.ts @@ -1,6 +1,5 @@ import { inject } from 'aurelia-framework'; import { I18N } from 'aurelia-i18n'; -import { arraysEqual } from '../services/index'; import { Editor, Column, @@ -8,6 +7,7 @@ import { MultipleSelectOption, SelectOption } from './../models/index'; +import { arraysEqual, CollectionService } from '../services/index'; import * as $ from 'jquery'; // height in pixel of the multiple-select DOM element @@ -16,7 +16,7 @@ const SELECT_ELEMENT_HEIGHT = 26; /** * Slickgrid editor class for multiple select lists */ -@inject(I18N) +@inject(CollectionService, I18N) export class MultipleSelectEditor implements Editor { /** The JQuery DOM element */ $editorElm: any; @@ -36,15 +36,21 @@ export class MultipleSelectEditor implements Editor { /** The options label/value object to use in the select list */ collection: SelectOption[] = []; + /** The property name for labels in the collection */ + labelName: string; + /** The property name for values in the collection */ valueName: string; - /** The property name for labels in the collection */ - labelName: string; + /** Grid options */ + gridOptions: GridOption; + + /** Do we translate the label? */ + enableTranslateLabel: boolean; - constructor(private i18n: I18N, private args: any) { - const gridOptions = this.args.grid.getOptions() as GridOption; - const params = gridOptions.params || this.args.column.params || {}; + constructor(private collectionService: CollectionService, private i18n: I18N, private args: any) { + this.gridOptions = this.args.grid.getOptions() as GridOption; + const params = this.gridOptions.params || this.args.column.params || {}; this.defaultOptions = { container: 'body', @@ -81,7 +87,32 @@ export class MultipleSelectEditor implements Editor { this.columnDef = this.args.column; - const editorTemplate = this.buildTemplateHtmlString(); + if (!this.columnDef || !this.columnDef.params || !this.columnDef.params.collection) { + throw new Error('[Aurelia-SlickGrid] You need to pass a "collection" on the params property in the column definition for ' + + 'the SingleSelect Editor to work correctly. Also each option should include ' + + 'a value/label pair (or value/labelKey when using Locale). For example: { params: { ' + + '{ collection: [{ value: true, label: \'True\' }, { value: false, label: \'False\'}] } } }'); + } + + this.enableTranslateLabel = (this.columnDef.params.enableTranslateLabel) ? this.columnDef.params.enableTranslateLabel : false; + let newCollection = this.columnDef.params.collection || []; + this.labelName = (this.columnDef.params.customStructure) ? this.columnDef.params.customStructure.label : 'label'; + this.valueName = (this.columnDef.params.customStructure) ? this.columnDef.params.customStructure.value : 'value'; + + // user might want to filter certain items of the collection + if (this.gridOptions && this.gridOptions.params && this.columnDef.params.collectionFilterBy) { + const filterBy = this.columnDef.params.collectionFilterBy; + newCollection = this.collectionService.filterCollection(newCollection, filterBy); + } + + // user might want to sort the collection + if (this.gridOptions && this.gridOptions.params && this.columnDef.params.collectionSortBy) { + const sortBy = this.columnDef.params.collectionSortBy; + newCollection = this.collectionService.sortCollection(newCollection, sortBy, this.enableTranslateLabel); + } + + this.collection = newCollection; + const editorTemplate = this.buildTemplateHtmlString(newCollection); this.createDomElement(editorTemplate); } @@ -170,20 +201,9 @@ export class MultipleSelectEditor implements Editor { } /** Build the template HTML string */ - private buildTemplateHtmlString() { - if (!this.columnDef || !this.columnDef.params || !this.columnDef.params.collection) { - throw new Error('[Aurelia-SlickGrid] You need to pass a "collection" on the params property in the column definition for ' + - 'the MultipleSelect Editor to work correctly. Also each option should include ' + - 'a value/label pair (or value/labelKey when using Locale). For example: { params: { ' + - '{ collection: [{ value: true, label: \'True\' },{ value: false, label: \'False\'}] } } }'); - } - this.collection = this.columnDef.params.collection || []; - this.labelName = (this.columnDef.params.customStructure) ? this.columnDef.params.customStructure.label : 'label'; - this.valueName = (this.columnDef.params.customStructure) ? this.columnDef.params.customStructure.value : 'value'; - const isEnabledTranslate = (this.columnDef.params.enableTranslateLabel) ? this.columnDef.params.enableTranslateLabel : false; - + private buildTemplateHtmlString(collection: any[]) { let options = ''; - this.collection.forEach((option: SelectOption) => { + collection.forEach((option: SelectOption) => { if (!option || (option[this.labelName] === undefined && option.labelKey === undefined)) { throw new Error('A collection with value/label (or value/labelKey when using ' + 'Locale) is required to populate the Select list, for example: ' + @@ -191,7 +211,7 @@ export class MultipleSelectEditor implements Editor { } const labelKey = (option.labelKey || option[this.labelName]) as string; - const textLabel = (option.labelKey || isEnabledTranslate) ? this.i18n.tr(labelKey || ' ') : labelKey; + const textLabel = (option.labelKey || this.enableTranslateLabel) ? this.i18n.tr(labelKey || ' ') : labelKey; options += ``; }); diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/editors/singleSelectEditor.ts b/aurelia-slickgrid/src/aurelia-slickgrid/editors/singleSelectEditor.ts index 3c03ba0db..ca0f79984 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/editors/singleSelectEditor.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/editors/singleSelectEditor.ts @@ -7,7 +7,7 @@ import { MultipleSelectOption, SelectOption } from '../models/index'; -import { findOrDefault } from '../services/index'; +import { findOrDefault, CollectionService } from '../services/index'; import * as $ from 'jquery'; // height in pixel of the multiple-select DOM element @@ -16,7 +16,7 @@ const SELECT_ELEMENT_HEIGHT = 26; /** * Slickgrid editor class for single select lists */ -@inject(I18N) +@inject(CollectionService, I18N) export class SingleSelectEditor implements Editor { /** The JQuery DOM element */ $editorElm: any; @@ -36,15 +36,21 @@ export class SingleSelectEditor implements Editor { /** The options label/value object to use in the select list */ collection: SelectOption[] = []; + /** The property name for labels in the collection */ + labelName: string; + /** The property name for values in the collection */ valueName: string; - /** The property name for labels in the collection */ - labelName: string; + /** Grid options */ + gridOptions: GridOption; + + /** Do we translate the label? */ + enableTranslateLabel: boolean; - constructor(private i18n: I18N, private args: any) { - const gridOptions = this.args.grid.getOptions() as GridOption; - const params = gridOptions.params || this.args.column.params || {}; + constructor(private collectionService: CollectionService, private i18n: I18N, private args: any) { + this.gridOptions = this.args.grid.getOptions() as GridOption; + const params = this.gridOptions.params || this.args.column.params || {}; this.defaultOptions = { container: 'body', @@ -74,7 +80,31 @@ export class SingleSelectEditor implements Editor { this.columnDef = this.args.column; - const editorTemplate = this.buildTemplateHtmlString(); + if (!this.columnDef || !this.columnDef.params || !this.columnDef.params.collection) { + throw new Error(`[Aurelia-SlickGrid] You need to pass a "collection" on the params property in the column definition for the MultipleSelect Editor to work correctly. + Also each option should include a value/label pair (or value/labelKey when using Locale). + For example: { params: { { collection: [{ value: true, label: 'True' },{ value: false, label: 'False'}] } } }`); + } + + this.enableTranslateLabel = (this.columnDef.params.enableTranslateLabel) ? this.columnDef.params.enableTranslateLabel : false; + let newCollection = this.columnDef.params.collection || []; + this.labelName = (this.columnDef.params.customStructure) ? this.columnDef.params.customStructure.label : 'label'; + this.valueName = (this.columnDef.params.customStructure) ? this.columnDef.params.customStructure.value : 'value'; + + // user might want to filter certain items of the collection + if (this.gridOptions.params && this.columnDef.params.collectionFilterBy) { + const filterBy = this.columnDef.params.collectionFilterBy; + newCollection = this.collectionService.filterCollection(newCollection, filterBy); + } + + // user might want to sort the collection + if (this.gridOptions.params && this.columnDef.params.collectionSortBy) { + const sortBy = this.columnDef.params.collectionSortBy; + newCollection = this.collectionService.sortCollection(newCollection, sortBy, this.enableTranslateLabel); + } + + this.collection = newCollection; + const editorTemplate = this.buildTemplateHtmlString(newCollection); this.createDomElement(editorTemplate); } @@ -163,27 +193,16 @@ export class SingleSelectEditor implements Editor { } /** Build the template HTML string */ - private buildTemplateHtmlString() { - if (!this.columnDef || !this.columnDef.params || !this.columnDef.params.collection) { - throw new Error('[Aurelia-SlickGrid] You need to pass a "collection" on the params property in the column definition for ' + - 'the SingleSelect Editor to work correctly. Also each option should include ' + - 'a value/label pair (or value/labelKey when using Locale). For example: { params: { ' + - '{ collection: [{ value: true, label: \'True\' }, { value: false, label: \'False\'}] } } }'); - } - this.collection = this.columnDef.params.collection || []; - this.labelName = (this.columnDef.params.customStructure) ? this.columnDef.params.customStructure.label : 'label'; - this.valueName = (this.columnDef.params.customStructure) ? this.columnDef.params.customStructure.value : 'value'; - const isEnabledTranslate = (this.columnDef.params.enableTranslateLabel) ? this.columnDef.params.enableTranslateLabel : false; - + private buildTemplateHtmlString(collection: any[]) { let options = ''; - this.collection.forEach((option: SelectOption) => { + collection.forEach((option: SelectOption) => { if (!option || (option[this.labelName] === undefined && option.labelKey === undefined)) { throw new Error('A collection with value/label (or value/labelKey when using ' + 'Locale) is required to populate the Select list, for example: { params: { ' + '{ collection: [ { value: \'1\', label: \'One\' } ] } } }'); } const labelKey = (option.labelKey || option[this.labelName]) as string; - const textLabel = (option.labelKey || isEnabledTranslate) ? this.i18n.tr(labelKey || ' ') : labelKey; + const textLabel = (option.labelKey || this.enableTranslateLabel) ? this.i18n.tr(labelKey || ' ') : labelKey; options += ``; }); diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/filters/multipleSelectFilter.ts b/aurelia-slickgrid/src/aurelia-slickgrid/filters/multipleSelectFilter.ts index 6aea1c77a..f7ba25e89 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/filters/multipleSelectFilter.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/filters/multipleSelectFilter.ts @@ -6,28 +6,34 @@ import { FilterArguments, FilterCallback, FilterType, + GridOption, HtmlElementPosition, MultipleSelectOption, SearchTerm, SelectOption } from './../models/index'; +import { CollectionService } from '../services/collection.service'; import * as $ from 'jquery'; -@inject(I18N) +@inject(CollectionService, I18N) export class MultipleSelectFilter implements Filter { $filterElm: any; grid: any; + gridOptions: GridOption; searchTerms: SearchTerm[]; columnDef: Column; callback: FilterCallback; defaultOptions: MultipleSelectOption; isFilled = false; filterType = FilterType.multipleSelect; + labelName: string; + valueName: string; + enableTranslateLabel = false; /** * Initialize the Filter */ - constructor(private i18n: I18N) { + constructor(private collectionService: CollectionService, private i18n: I18N) { // default options used by this Filter, user can overwrite any of these by passing "otions" this.defaultOptions = { container: 'body', @@ -68,8 +74,31 @@ export class MultipleSelectFilter implements Filter { this.columnDef = args.columnDef; this.searchTerms = args.searchTerms || []; + if (!this.grid || !this.columnDef || !this.columnDef.filter || !this.columnDef.filter.collection) { + throw new Error(`[Aurelia-SlickGrid] You need to pass a "collection" for the MultipleSelect Filter to work correctly. Also each option should include a value/label pair (or value/labelKey when using Locale). For example:: { filter: type: FilterType.multipleSelect, collection: [{ value: true, label: 'True' }, { value: false, label: 'False'}] }`); + } + + this.enableTranslateLabel = this.columnDef.filter.enableTranslateLabel || false; + this.labelName = (this.columnDef.filter.customStructure) ? this.columnDef.filter.customStructure.label : 'label'; + this.valueName = (this.columnDef.filter.customStructure) ? this.columnDef.filter.customStructure.value : 'value'; + + let newCollection = this.columnDef.filter.collection || []; + this.gridOptions = this.grid.getOptions(); + + // user might want to filter certain items of the collection + if (this.gridOptions.params && this.columnDef.filter.collectionFilterBy) { + const filterBy = this.columnDef.filter.collectionFilterBy; + newCollection = this.collectionService.filterCollection(newCollection, filterBy); + } + + // user might want to sort the collection + if (this.gridOptions.params && this.columnDef.filter.collectionSortBy) { + const sortBy = this.columnDef.filter.collectionSortBy; + newCollection = this.collectionService.sortCollection(newCollection, sortBy, this.enableTranslateLabel); + } + // step 1, create HTML string template - const filterTemplate = this.buildTemplateHtmlString(); + const filterTemplate = this.buildTemplateHtmlString(newCollection); // step 2, create the DOM Element of the filter & pre-load search terms // also subscribe to the onClose event @@ -117,26 +146,18 @@ export class MultipleSelectFilter implements Filter { /** * Create the HTML template as a string */ - private buildTemplateHtmlString() { - if (!this.columnDef || !this.columnDef.filter || !this.columnDef.filter.collection) { - throw new Error(`[Aurelia-SlickGrid] You need to pass a "collection" for the MultipleSelect Filter to work correctly. Also each option should include a value/label pair (or value/labelKey when using Locale). For example:: { filter: type: FilterType.multipleSelect, collection: [{ value: true, label: 'True' }, { value: false, label: 'False'}] }`); - } - const optionCollection = this.columnDef.filter.collection || []; - const labelName = (this.columnDef.filter.customStructure) ? this.columnDef.filter.customStructure.label : 'label'; - const valueName = (this.columnDef.filter.customStructure) ? this.columnDef.filter.customStructure.value : 'value'; - const isEnabledTranslate = (this.columnDef.filter.enableTranslateLabel) ? this.columnDef.filter.enableTranslateLabel : false; - + private buildTemplateHtmlString(optionCollection: any[]) { let options = ''; optionCollection.forEach((option: SelectOption) => { - if (!option || (option[labelName] === undefined && option.labelKey === undefined)) { + if (!option || (option[this.labelName] === undefined && option.labelKey === undefined)) { throw new Error(`A collection with value/label (or value/labelKey when using Locale) is required to populate the Select list, for example:: { filter: type: FilterType.multipleSelect, collection: [ { value: '1', label: 'One' } ]')`); } - const labelKey = (option.labelKey || option[labelName]) as string; - const selected = (this.findValueInSearchTerms(option[valueName]) >= 0) ? 'selected' : ''; - const textLabel = ((option.labelKey || isEnabledTranslate) && this.i18n && typeof this.i18n.tr === 'function') ? this.i18n.tr(labelKey || ' ') : labelKey; + const labelKey = (option.labelKey || option[this.labelName]) as string; + const selected = (this.findValueInSearchTerms(option[this.valueName]) >= 0) ? 'selected' : ''; + const textLabel = ((option.labelKey || this.enableTranslateLabel) && this.i18n && typeof this.i18n.tr === 'function') ? this.i18n.tr(labelKey || ' ') : labelKey; // html text of each select option - options += ``; + options += ``; // if there's a search term, we will add the "filled" class for styling purposes if (selected) { diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/filters/singleSelectFilter.ts b/aurelia-slickgrid/src/aurelia-slickgrid/filters/singleSelectFilter.ts index bad8f03f7..453bd3538 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/filters/singleSelectFilter.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/filters/singleSelectFilter.ts @@ -6,25 +6,31 @@ import { FilterType, FilterArguments, FilterCallback, + GridOption, HtmlElementPosition, MultipleSelectOption, SearchTerm, SelectOption } from './../models/index'; +import { CollectionService } from '../services/collection.service'; import * as $ from 'jquery'; -@inject(I18N) +@inject(CollectionService, I18N) export class SingleSelectFilter implements Filter { $filterElm: any; grid: any; + gridOptions: GridOption; searchTerm: SearchTerm; columnDef: Column; callback: FilterCallback; defaultOptions: MultipleSelectOption; filterType = FilterType.singleSelect; isFilled = false; + labelName: string; + valueName: string; + enableTranslateLabel = false; - constructor(private i18n: I18N) { + constructor(private collectionService: CollectionService, private i18n: I18N) { // default options used by this Filter, user can overwrite any of these by passing "otions" this.defaultOptions = { container: 'body', @@ -60,8 +66,31 @@ export class SingleSelectFilter implements Filter { this.columnDef = args.columnDef; this.searchTerm = args.searchTerm || ''; + if (!this.grid || !this.columnDef || !this.columnDef.filter || !this.columnDef.filter.collection) { + throw new Error(`[Aurelia-SlickGrid] You need to pass a "collection" for the MultipleSelect Filter to work correctly. Also each option should include a value/label pair (or value/labelKey when using Locale). For example:: { filter: type: FilterType.multipleSelect, collection: [{ value: true, label: 'True' }, { value: false, label: 'False'}] }`); + } + + this.enableTranslateLabel = this.columnDef.filter.enableTranslateLabel || false; + this.labelName = (this.columnDef.filter.customStructure) ? this.columnDef.filter.customStructure.label : 'label'; + this.valueName = (this.columnDef.filter.customStructure) ? this.columnDef.filter.customStructure.value : 'value'; + + let newCollection = this.columnDef.filter.collection || []; + this.gridOptions = this.grid.getOptions(); + + // user might want to filter certain items of the collection + if (this.gridOptions.params && this.columnDef.filter.collectionFilterBy) { + const filterBy = this.columnDef.filter.collectionFilterBy; + newCollection = this.collectionService.filterCollection(newCollection, filterBy); + } + + // user might want to sort the collection + if (this.gridOptions.params && this.columnDef.filter.collectionSortBy) { + const sortBy = this.columnDef.filter.collectionSortBy; + newCollection = this.collectionService.sortCollection(newCollection, sortBy, this.enableTranslateLabel); + } + // step 1, create HTML string template - const filterTemplate = this.buildTemplateHtmlString(); + const filterTemplate = this.buildTemplateHtmlString(newCollection || []); // step 2, create the DOM Element of the filter & pre-load search term this.createDomElement(filterTemplate); @@ -108,27 +137,19 @@ export class SingleSelectFilter implements Filter { /** * Create the HTML template as a string */ - private buildTemplateHtmlString() { - if (!this.columnDef || !this.columnDef.filter || !this.columnDef.filter.collection) { - throw new Error(`[Aurelia-SlickGrid] You need to pass a "collection" for the SingleSelect Filter to work correctly. Also each option should include a value/label pair (or value/labelKey when using Locale). For example:: { filter: type: FilterType.singleSelect, collection: [{ value: true, label: 'True' }, { value: false, label: 'False'}] }`); - } - const optionCollection = this.columnDef.filter.collection || []; - const labelName = (this.columnDef.filter.customStructure) ? this.columnDef.filter.customStructure.label : 'label'; - const valueName = (this.columnDef.filter.customStructure) ? this.columnDef.filter.customStructure.value : 'value'; - const isEnabledTranslate = (this.columnDef.filter.enableTranslateLabel) ? this.columnDef.filter.enableTranslateLabel : false; - + private buildTemplateHtmlString(optionCollection: any[]) { let options = ''; optionCollection.forEach((option: SelectOption) => { - if (!option || (option[labelName] === undefined && option.labelKey === undefined)) { + if (!option || (option[this.labelName] === undefined && option.labelKey === undefined)) { throw new Error(`A collection with value/label (or value/labelKey when using Locale) is required to populate the Select list, for example:: { filter: type: FilterType.singleSelect, collection: [ { value: '1', label: 'One' } ]')`); } - const labelKey = (option.labelKey || option[labelName]) as string; - const selected = (option[valueName] === this.searchTerm) ? 'selected' : ''; - const textLabel = ((option.labelKey || isEnabledTranslate) && this.i18n && typeof this.i18n.tr === 'function') ? this.i18n.tr(labelKey || ' ') : labelKey; + const labelKey = (option.labelKey || option[this.labelName]) as string; + const selected = (option[this.valueName] === this.searchTerm) ? 'selected' : ''; + const textLabel = ((option.labelKey || this.enableTranslateLabel) && this.i18n && typeof this.i18n.tr === 'function') ? this.i18n.tr(labelKey || ' ') : labelKey; // html text of each select option - options += ``; + options += ``; // if there's a search term, we will add the "filled" class for styling purposes if (selected) { diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/models/collectionFilterBy.interface.ts b/aurelia-slickgrid/src/aurelia-slickgrid/models/collectionFilterBy.interface.ts new file mode 100644 index 000000000..53d9a6df4 --- /dev/null +++ b/aurelia-slickgrid/src/aurelia-slickgrid/models/collectionFilterBy.interface.ts @@ -0,0 +1,7 @@ +import { OperatorType } from './operatorType.enum'; + +export interface CollectionFilterBy { + property: string; + value: any; + operator?: OperatorType.equal | OperatorType.notEqual; +} diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/models/collectionSortBy.interface.ts b/aurelia-slickgrid/src/aurelia-slickgrid/models/collectionSortBy.interface.ts new file mode 100644 index 000000000..8bec31efd --- /dev/null +++ b/aurelia-slickgrid/src/aurelia-slickgrid/models/collectionSortBy.interface.ts @@ -0,0 +1,7 @@ +import { FieldType, OperatorType } from './index'; + +export interface CollectionSortBy { + property: string; + sortDesc?: boolean; + fieldType?: FieldType; +} diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/models/columnFilter.interface.ts b/aurelia-slickgrid/src/aurelia-slickgrid/models/columnFilter.interface.ts index 7a4114c5c..600c9a028 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/models/columnFilter.interface.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/models/columnFilter.interface.ts @@ -1,4 +1,6 @@ import { + CollectionFilterBy, + CollectionSortBy, Column, Filter, FilterType, @@ -37,6 +39,12 @@ export interface ColumnFilter { /** A collection of items/options (commonly used with a Select/Multi-Select Filter) */ collection?: any[]; + /** We could filter some items from the collection */ + collectionFilterBy?: CollectionFilterBy; + + /** We could sort the collection by their value, or by translated value when enableTranslateLabel is True */ + collectionSortBy?: CollectionSortBy; + /** Options that could be provided to the Filter, example: { container: 'body', maxHeight: 250} */ filterOptions?: MultipleSelectOption | any; diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/models/index.ts b/aurelia-slickgrid/src/aurelia-slickgrid/models/index.ts index 3af8e3ff8..30b5a0cbc 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/models/index.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/models/index.ts @@ -6,6 +6,8 @@ export * from './backendServiceOption.interface'; export * from './caseType'; export * from './cellArgs.interface'; export * from './checkboxSelector.interface'; +export * from './collectionFilterBy.interface'; +export * from './collectionSortBy.interface'; export * from './column.interface'; export * from './columnFilter.interface'; export * from './columnFilters.interface'; @@ -63,5 +65,6 @@ export * from './slickEvent.interface'; export * from './sortChanged.interface'; export * from './sortChangedArgs.interface'; export * from './sortDirection.enum'; +export * from './sortDirectionNumber.enum'; export * from './sortDirectionString'; export * from './sorter.interface'; diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/models/multipleSelectOption.interface.ts b/aurelia-slickgrid/src/aurelia-slickgrid/models/multipleSelectOption.interface.ts index ab4987032..109dc7a19 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/models/multipleSelectOption.interface.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/models/multipleSelectOption.interface.ts @@ -124,7 +124,7 @@ export interface MultipleSelectOption { setSelects?: (value: string | string[]) => void; /** The item styler function, return style string to custom the item style such as background: red. The function take one parameter: value. */ - styler?: () => void; + styler?: (value: string) => void; /** Returns HTML label attribute of a DOM element */ labelTemplate?: (elm: any) => any; @@ -155,11 +155,18 @@ export interface MultipleSelectOption { onBlur?: () => void; /** Fires when a an optgroup label is clicked on. */ - onOptgroupClick?: () => void; + onOptgroupClick?: (view: MultipleSelectView) => void; /** Fires when a checkbox is checked or unchecked. */ - onClick?: () => void; + onClick?: (view: MultipleSelectView) => void; /** Fires when a checkbox filter is changed. */ onFilter?: () => void; } + +export interface MultipleSelectView { + label: string; + value: any; + checked: boolean; + instance: any; +} diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/models/sortDirectionNumber.enum.ts b/aurelia-slickgrid/src/aurelia-slickgrid/models/sortDirectionNumber.enum.ts new file mode 100644 index 000000000..8dc317b14 --- /dev/null +++ b/aurelia-slickgrid/src/aurelia-slickgrid/models/sortDirectionNumber.enum.ts @@ -0,0 +1,5 @@ +export enum SortDirectionNumber { + asc = 1, + desc = -1, + neutral = 0, +} diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/services/collection.service.ts b/aurelia-slickgrid/src/aurelia-slickgrid/services/collection.service.ts new file mode 100644 index 000000000..0c2f2d9d7 --- /dev/null +++ b/aurelia-slickgrid/src/aurelia-slickgrid/services/collection.service.ts @@ -0,0 +1,63 @@ +import { inject } from 'aurelia-framework'; +import { I18N } from 'aurelia-i18n'; +import { + CollectionFilterBy, + CollectionSortBy, + FieldType, + OperatorType, +} from './../models/index'; +import { sortByFieldType } from '../sorters/sorterUtilities'; + +@inject(I18N) +export class CollectionService { + constructor(private i18n: I18N) { } + + /** + * Filter items from a collection + * @param collection + * @param filterBy + */ + filterCollection(collection: any[], filterBy: CollectionFilterBy): any[] { + let filteredCollection: any[] = []; + + if (filterBy) { + const property = filterBy.property || ''; + const operator = filterBy.operator || OperatorType.equal; + const value = filterBy.value || ''; + + if (operator === OperatorType.equal) { + filteredCollection = collection.filter((item) => item[property] !== value); + } else { + filteredCollection = collection.filter((item) => item[property] === value); + } + } + + return filteredCollection; + } + + /** + * Sort items in a collection + * @param collection + * @param sortBy + * @param columnDef + * @param translate + */ + sortCollection(collection: any[], sortBy: CollectionSortBy, enableTranslateLabel?: boolean): any[] { + let sortedCollection: any[] = []; + + if (sortBy) { + const property = sortBy.property || ''; + const sortDirection = sortBy.hasOwnProperty('sortDesc') ? (sortBy.sortDesc ? -1 : 1) : 1; + const fieldType = sortBy.fieldType || FieldType.string; + + sortedCollection = collection.sort((dataRow1: any, dataRow2: any) => { + const value1 = (enableTranslateLabel) ? this.i18n.tr(dataRow1[property] || ' ') : dataRow1[property]; + const value2 = (enableTranslateLabel) ? this.i18n.tr(dataRow2[property] || ' ') : dataRow2[property]; + const result = sortByFieldType(value1, value2, fieldType, sortDirection); + return result; + }); + } + + return sortedCollection; + } +} diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/services/index.ts b/aurelia-slickgrid/src/aurelia-slickgrid/services/index.ts index df7b159f7..808370646 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/services/index.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/services/index.ts @@ -1,3 +1,4 @@ +export * from './collection.service'; export * from './controlAndPlugin.service'; export * from './export.service'; export * from './filter.service'; diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/services/sort.service.ts b/aurelia-slickgrid/src/aurelia-slickgrid/services/sort.service.ts index 61a1d64c0..a7f9f8b33 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/services/sort.service.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/services/sort.service.ts @@ -1,7 +1,19 @@ import { inject } from 'aurelia-framework'; import { EventAggregator } from 'aurelia-event-aggregator'; -import { Column, FieldType, GridOption, SlickEvent, SortChanged, SortDirection, CurrentSorter, CellArgs, SortDirectionString } from './../models/index'; +import { + Column, + FieldType, + GridOption, + SlickEvent, + SortChanged, + SortDirection, + CurrentSorter, + CellArgs, + SortDirectionNumber, + SortDirectionString +} from './../models/index'; import { Sorters } from './../sorters/index'; +import { sortByFieldType } from '../sorters/sorterUtilities'; // using external non-typed js libraries declare var Slick: any; @@ -148,36 +160,14 @@ export class SortService { for (let i = 0, l = sortColumns.length; i < l; i++) { const columnSortObj = sortColumns[i]; if (columnSortObj && columnSortObj.sortCol) { - const sortDirection = columnSortObj.sortAsc ? 1 : -1; - const sortField = columnSortObj.sortCol.queryField || columnSortObj.sortCol.queryFieldSorter || columnSortObj.sortCol.field; - const fieldType = columnSortObj.sortCol.type || 'string'; + const sortDirection = columnSortObj.sortAsc ? SortDirectionNumber.asc : SortDirectionNumber.desc; + const sortField = columnSortObj.sortCol.queryField || columnSortObj.sortCol.queryFieldFilter || columnSortObj.sortCol.field; + const fieldType = columnSortObj.sortCol.type || FieldType.string; const value1 = dataRow1[sortField]; const value2 = dataRow2[sortField]; - let result = 0; - - switch (fieldType) { - case FieldType.number: - result = Sorters.numeric(value1, value2, sortDirection); - break; - case FieldType.date: - result = Sorters.date(value1, value2, sortDirection); - break; - case FieldType.dateIso: - result = Sorters.dateIso(value1, value2, sortDirection); - break; - case FieldType.dateUs: - result = Sorters.dateUs(value1, value2, sortDirection); - break; - case FieldType.dateUsShort: - result = Sorters.dateUsShort(value1, value2, sortDirection); - break; - default: - result = Sorters.string(value1, value2, sortDirection); - break; - } - - if (result !== 0) { - return result; + const sortResult = sortByFieldType(value1, value2, fieldType, sortDirection); + if (sortResult !== SortDirectionNumber.neutral) { + return sortResult; } } } diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/sorters/index.ts b/aurelia-slickgrid/src/aurelia-slickgrid/sorters/index.ts index 39a60db8a..989ace586 100644 --- a/aurelia-slickgrid/src/aurelia-slickgrid/sorters/index.ts +++ b/aurelia-slickgrid/src/aurelia-slickgrid/sorters/index.ts @@ -1,3 +1,4 @@ +import { SortDirectionNumber } from './../models/sortDirectionNumber.enum'; import { dateUsShortSorter } from './dateUsShortSorter'; import { dateSorter } from './dateSorter'; import { dateIsoSorter } from './dateIsoSorter'; diff --git a/aurelia-slickgrid/src/aurelia-slickgrid/sorters/sorterUtilities.ts b/aurelia-slickgrid/src/aurelia-slickgrid/sorters/sorterUtilities.ts new file mode 100644 index 000000000..2f7436031 --- /dev/null +++ b/aurelia-slickgrid/src/aurelia-slickgrid/sorters/sorterUtilities.ts @@ -0,0 +1,29 @@ +import { FieldType } from './../models/fieldType.enum'; +import { Sorters } from './index'; + +export function sortByFieldType(value1: any, value2: any, fieldType: FieldType, sortDirection: number) { + let sortResult = 0; + + switch (fieldType) { + case FieldType.number: + sortResult = Sorters.numeric(value1, value2, sortDirection); + break; + case FieldType.date: + sortResult = Sorters.date(value1, value2, sortDirection); + break; + case FieldType.dateIso: + sortResult = Sorters.dateIso(value1, value2, sortDirection); + break; + case FieldType.dateUs: + sortResult = Sorters.dateUs(value1, value2, sortDirection); + break; + case FieldType.dateUsShort: + sortResult = Sorters.dateUsShort(value1, value2, sortDirection); + break; + default: + sortResult = Sorters.string(value1, value2, sortDirection); + break; + } + + return sortResult; +} diff --git a/aurelia-slickgrid/src/examples/slickgrid/example12.ts b/aurelia-slickgrid/src/examples/slickgrid/example12.ts index c9c5acca2..eb16e1067 100644 --- a/aurelia-slickgrid/src/examples/slickgrid/example12.ts +++ b/aurelia-slickgrid/src/examples/slickgrid/example12.ts @@ -15,7 +15,7 @@ export class Example12 {