From 86b1214b633890273f870c2c9d5ac7b026ba9d29 Mon Sep 17 00:00:00 2001 From: Ghislain Beaulac Date: Fri, 19 Jul 2019 19:32:14 -0400 Subject: [PATCH] feat(translate): make ngx-translate an optional dependency --- src/app/examples/grid-menu.component.ts | 2 +- .../components/angular-slickgrid.component.ts | 26 ++-- .../modules/angular-slickgrid/constants.ts | 7 ++ .../extensions/extensionUtility.ts | 10 +- .../extensions/gridMenuExtension.ts | 7 +- .../extensions/headerMenuExtension.ts | 7 +- .../filters/compoundDateFilter.ts | 17 +-- .../filters/compoundInputFilter.ts | 15 +-- .../filters/filterFactory.ts | 4 +- .../filters/nativeSelectFilter.ts | 3 +- .../angular-slickgrid/filters/selectFilter.ts | 112 +++++++++--------- .../services/collection.service.ts | 8 +- .../services/export.service.ts | 8 +- .../services/extension.service.ts | 10 +- 14 files changed, 137 insertions(+), 99 deletions(-) diff --git a/src/app/examples/grid-menu.component.ts b/src/app/examples/grid-menu.component.ts index a45cc0b2b..f56eb677c 100644 --- a/src/app/examples/grid-menu.component.ts +++ b/src/app/examples/grid-menu.component.ts @@ -16,7 +16,7 @@ export class GridMenuComponent implements OnInit {
  • You can change the Grid Menu icon, for example "fa-ellipsis-v"    (which is shown in this example)
  • By default the Grid Menu shows all columns which you can show/hide them
  • You can configure multiple custom "commands" to show up in the Grid Menu and use the "onGridMenuCommand()" callback
  • -
  • Doing a "right+click" over any column header will also provide a way to show/hide a column (via the Column Picker Plugin)
  • +
  • Doing a "right + click" over any column header will also provide a way to show/hide a column (via the Column Picker Plugin)
  • You can also show the Grid Menu anywhere on your page
  • `; diff --git a/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts b/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts index a8c527e36..2a6e38034 100644 --- a/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts +++ b/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts @@ -7,7 +7,7 @@ import 'slickgrid/slick.grid'; import 'slickgrid/slick.dataview'; // ...then everything else... -import { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Injectable, Input, Output, OnDestroy, OnInit } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Injectable, Input, Output, OnDestroy, OnInit, Optional } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { GlobalGridOptions } from './../global-grid-options'; import { titleCase, unsubscribeAllObservables } from './../services/utilities'; @@ -168,7 +168,7 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn private resizer: ResizerService, private sharedService: SharedService, private sortService: SortService, - private translate: TranslateService, + @Optional() private translate: TranslateService, @Inject('config') private forRootConfig: GridOption ) { } @@ -400,16 +400,18 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn bindDifferentHooks(grid: any, gridOptions: GridOption, dataView: any) { // on locale change, we have to manually translate the Headers, GridMenu - this.subscriptions.push( - this.translate.onLangChange.subscribe((event) => { - if (gridOptions.enableTranslate) { - this.extensionService.translateColumnHeaders(); - this.extensionService.translateColumnPicker(); - this.extensionService.translateGridMenu(); - this.extensionService.translateHeaderMenu(); - } - }) - ); + if (this.translate && this.translate.onLangChange) { + this.subscriptions.push( + this.translate.onLangChange.subscribe((event) => { + if (gridOptions.enableTranslate) { + this.extensionService.translateColumnHeaders(); + this.extensionService.translateColumnPicker(); + this.extensionService.translateGridMenu(); + this.extensionService.translateHeaderMenu(); + } + }) + ); + } // if user entered some Columns "presets", we need to reflect them all in the grid if (gridOptions.presets && Array.isArray(gridOptions.presets.columns) && gridOptions.presets.columns.length > 0) { diff --git a/src/app/modules/angular-slickgrid/constants.ts b/src/app/modules/angular-slickgrid/constants.ts index f031051dd..33f8a6135 100644 --- a/src/app/modules/angular-slickgrid/constants.ts +++ b/src/app/modules/angular-slickgrid/constants.ts @@ -1,9 +1,13 @@ export class Constants { + static TEXT_ALL_SELECTED = 'All Selected'; static TEXT_CANCEL = 'Cancel'; static TEXT_CLEAR_ALL_FILTERS = 'Clear All Filters'; static TEXT_CLEAR_ALL_SORTING = 'Clear All Sorting'; + static TEXT_CONTAINS = 'Contains'; static TEXT_COLUMNS = 'Columns'; static TEXT_COMMANDS = 'Commands'; + static TEXT_EQUALS = 'Equals'; + static TEXT_ENDS_WITH = 'Ends With'; static TEXT_EXPORT_IN_CSV_FORMAT = 'Export in CSV format'; static TEXT_EXPORT_IN_TEXT_FORMAT = 'Export in Text format (Tab delimited)'; static TEXT_FORCE_FIT_COLUMNS = 'Force fit columns'; @@ -13,11 +17,14 @@ export class Constants { static TEXT_REMOVE_FILTER = 'Remove Filter'; static TEXT_REMOVE_SORT = 'Remove Sort'; static TEXT_SAVE = 'Save'; + static TEXT_SELECT_ALL = 'Select All'; static TEXT_SYNCHRONOUS_RESIZE = 'Synchronous resize'; static TEXT_SORT_ASCENDING = 'Sort Ascending'; static TEXT_SORT_DESCENDING = 'Sort Descending'; + static TEXT_STARTS_WITH = 'Starts With'; static TEXT_TOGGLE_FILTER_ROW = 'Toggle Filter Row'; static TEXT_TOGGLE_PRE_HEADER_ROW = 'Toggle Pre-Header Row'; + static TEXT_X_OF_Y_SELECTED = '# of % selected'; static VALIDATION_REQUIRED_FIELD = 'Field is required'; static VALIDATION_EDITOR_VALID_NUMBER = 'Please enter a valid number'; static VALIDATION_EDITOR_VALID_INTEGER = 'Please enter a valid integer number'; diff --git a/src/app/modules/angular-slickgrid/extensions/extensionUtility.ts b/src/app/modules/angular-slickgrid/extensions/extensionUtility.ts index 4de399a0f..9fb327b4d 100644 --- a/src/app/modules/angular-slickgrid/extensions/extensionUtility.ts +++ b/src/app/modules/angular-slickgrid/extensions/extensionUtility.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Optional } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { Constants } from '../constants'; import { ExtensionName } from '../models/index'; @@ -8,7 +8,11 @@ declare function require(name: string); @Injectable() export class ExtensionUtility { - constructor(private sharedService: SharedService, private translate: TranslateService) { } + constructor(private sharedService: SharedService, @Optional() private translate: TranslateService) { + if (this.sharedService.gridOptions && this.sharedService.gridOptions.enableTranslate && (!this.translate || !this.translate.instant)) { + throw new Error('[Angular-Slickgrid] requires "ngx-translate" to be installed and configured when the grid option "enableTranslate" is enabled.'); + } + } /** * Remove a column from the grid by it's index in the grid @@ -127,7 +131,7 @@ export class ExtensionUtility { if (Array.isArray(items)) { for (const item of items) { if (item[inputKey]) { - item[outputKey] = this.translate.instant(item[inputKey]); + item[outputKey] = this.translate && this.translate && this.translate.instant && this.translate.instant(item[inputKey]); } } } diff --git a/src/app/modules/angular-slickgrid/extensions/gridMenuExtension.ts b/src/app/modules/angular-slickgrid/extensions/gridMenuExtension.ts index fa8ce6223..01be9e2f2 100644 --- a/src/app/modules/angular-slickgrid/extensions/gridMenuExtension.ts +++ b/src/app/modules/angular-slickgrid/extensions/gridMenuExtension.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Optional } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { Constants } from '../constants'; import { @@ -37,8 +37,11 @@ export class GridMenuExtension implements Extension { private filterService: FilterService, private sharedService: SharedService, private sortService: SortService, - private translate: TranslateService, + @Optional() private translate: TranslateService, ) { + if (this.sharedService.gridOptions && this.sharedService.gridOptions.enableTranslate && (!this.translate || !this.translate.instant)) { + throw new Error('[Angular-Slickgrid] requires "ngx-translate" to be installed and configured when the grid option "enableTranslate" is enabled.'); + } this._eventHandler = new Slick.EventHandler(); } diff --git a/src/app/modules/angular-slickgrid/extensions/headerMenuExtension.ts b/src/app/modules/angular-slickgrid/extensions/headerMenuExtension.ts index 491392c52..153f4ef91 100644 --- a/src/app/modules/angular-slickgrid/extensions/headerMenuExtension.ts +++ b/src/app/modules/angular-slickgrid/extensions/headerMenuExtension.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Optional } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { Constants } from '../constants'; import { @@ -31,8 +31,11 @@ export class HeaderMenuExtension implements Extension { private filterService: FilterService, private sharedService: SharedService, private sortService: SortService, - private translate: TranslateService, + @Optional() private translate: TranslateService, ) { + if (this.sharedService.gridOptions && this.sharedService.gridOptions.enableTranslate && (!this.translate || !this.translate.instant)) { + throw new Error('[Angular-Slickgrid] requires "ngx-translate" to be installed and configured when the grid option "enableTranslate" is enabled.'); + } this._eventHandler = new Slick.EventHandler(); } diff --git a/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts b/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts index d9302145e..ec4e85f40 100644 --- a/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts +++ b/src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts @@ -13,6 +13,7 @@ import { SearchTerm, } from './../models/index'; import Flatpickr from 'flatpickr'; +import { Optional } from '@angular/core'; // use Flatpickr from import or 'require', whichever works first declare function require(name: string): any; @@ -35,7 +36,7 @@ export class CompoundDateFilter implements Filter { columnDef: Column; callback: FilterCallback; - constructor(private translate: TranslateService) { } + constructor(@Optional() private translate: TranslateService) { } /** Getter for the Grid Options pulled through the Grid Object */ private get gridOptions(): GridOption { @@ -123,7 +124,7 @@ export class CompoundDateFilter implements Filter { private buildDatePickerInput(searchTerm?: SearchTerm) { const inputFormat = mapFlatpickrDateFormatWithFieldType(this.columnDef.type || FieldType.dateIso); const outputFormat = mapFlatpickrDateFormatWithFieldType(this.columnDef.outputType || this.columnDef.type || FieldType.dateUtc); - let currentLocale = this.translate.currentLang || 'en'; + let currentLocale = this.translate && this.translate.currentLang || 'en'; if (currentLocale.length > 2) { currentLocale = currentLocale.substring(0, 2); } @@ -180,12 +181,12 @@ export class CompoundDateFilter implements Filter { private getOptionValues(): { operator: OperatorString, description: string }[] { return [ { operator: '' as OperatorString, description: '' }, - { operator: '=' as OperatorString, description: '' }, - { operator: '<' as OperatorString, description: '' }, - { operator: '<=' as OperatorString, description: '' }, - { operator: '>' as OperatorString, description: '' }, - { operator: '>=' as OperatorString, description: '' }, - { operator: '<>' as OperatorString, description: '' } + { operator: '=' as OperatorString, description: '=' }, + { operator: '<' as OperatorString, description: '<' }, + { operator: '<=' as OperatorString, description: '<=' }, + { operator: '>' as OperatorString, description: '>' }, + { operator: '>=' as OperatorString, description: '>=' }, + { operator: '<>' as OperatorString, description: '<>' } ]; } diff --git a/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts b/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts index adc030ad6..aa3268093 100644 --- a/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts +++ b/src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts @@ -1,3 +1,4 @@ +import { Constants } from './../constants'; import { TranslateService } from '@ngx-translate/core'; import { FieldType } from './../models/index'; import { @@ -149,19 +150,19 @@ export class CompoundInputFilter implements Filter { switch (type) { case FieldType.string: optionValues = [ - { operator: '' as OperatorString, description: this.translate.instant('CONTAINS') }, - { operator: '=' as OperatorString, description: this.translate.instant('EQUALS') }, - { operator: 'a*' as OperatorString, description: this.translate.instant('STARTS_WITH') }, - { operator: '*z' as OperatorString, description: this.translate.instant('ENDS_WITH') }, + { operator: '' as OperatorString, description: this.translate && this.translate.instant && this.translate.instant('CONTAINS') || Constants.TEXT_CONTAINS }, + { operator: '=' as OperatorString, description: this.translate && this.translate.instant && this.translate.instant('EQUALS') || Constants.TEXT_EQUALS }, + { operator: 'a*' as OperatorString, description: this.translate && this.translate.instant && this.translate.instant('STARTS_WITH') || Constants.TEXT_STARTS_WITH }, + { operator: '*z' as OperatorString, description: this.translate && this.translate.instant && this.translate.instant('ENDS_WITH') || Constants.TEXT_CONTAINS }, /* - { operator: 'IN' as OperatorString, description: this.translate.instant('IN_COLLECTION_SEPERATED_BY_COMMA') }, - { operator: 'NIN' as OperatorString, description: this.translate.instant('NOT_IN_COLLECTION_SEPERATED_BY_COMMA') }, + { operator: 'IN' as OperatorString, description: this.translate && this.translate.instant && this.translate.instant('IN_COLLECTION_SEPERATED_BY_COMMA') }, + { operator: 'NIN' as OperatorString, description: this.translate && this.translate.instant && this.translate.instant('NOT_IN_COLLECTION_SEPERATED_BY_COMMA') }, */ ]; break; default: optionValues = [ - { operator: '' as OperatorString, description: this.translate.instant('CONTAINS') }, + { operator: '' as OperatorString, description: this.translate && this.translate.instant && this.translate.instant('CONTAINS') || Constants.TEXT_CONTAINS }, { operator: '=' as OperatorString, description: '' }, { operator: '<' as OperatorString, description: '' }, { operator: '<=' as OperatorString, description: '' }, diff --git a/src/app/modules/angular-slickgrid/filters/filterFactory.ts b/src/app/modules/angular-slickgrid/filters/filterFactory.ts index 9bcf845cd..dd612063e 100644 --- a/src/app/modules/angular-slickgrid/filters/filterFactory.ts +++ b/src/app/modules/angular-slickgrid/filters/filterFactory.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Optional } from '@angular/core'; import { Filter } from '../models/filter.interface'; import { ColumnFilter } from '../models'; import { SlickgridConfig } from '../slickgrid-config'; @@ -12,7 +12,7 @@ export class FilterFactory { */ private _options: any; - constructor(private config: SlickgridConfig, private translate: TranslateService, private collectionService: CollectionService) { + constructor(private config: SlickgridConfig, @Optional() private translate: TranslateService, private collectionService: CollectionService) { this._options = this.config.options; } diff --git a/src/app/modules/angular-slickgrid/filters/nativeSelectFilter.ts b/src/app/modules/angular-slickgrid/filters/nativeSelectFilter.ts index bb26d6f91..07671fc63 100644 --- a/src/app/modules/angular-slickgrid/filters/nativeSelectFilter.ts +++ b/src/app/modules/angular-slickgrid/filters/nativeSelectFilter.ts @@ -8,6 +8,7 @@ import { OperatorString, SearchTerm, } from './../models/index'; +import { Optional } from '@angular/core'; // using external non-typed js libraries declare var $: any; @@ -21,7 +22,7 @@ export class NativeSelectFilter implements Filter { columnDef: Column; callback: FilterCallback; - constructor(private translate: TranslateService) { } + constructor(@Optional() private translate: TranslateService) { } get operator(): OperatorType | OperatorString { return (this.columnDef && this.columnDef.filter && this.columnDef.filter.operator) || OperatorType.equal; diff --git a/src/app/modules/angular-slickgrid/filters/selectFilter.ts b/src/app/modules/angular-slickgrid/filters/selectFilter.ts index 6693d9bd4..94fc2c924 100644 --- a/src/app/modules/angular-slickgrid/filters/selectFilter.ts +++ b/src/app/modules/angular-slickgrid/filters/selectFilter.ts @@ -1,3 +1,5 @@ +import { Constants } from './../constants'; +import { Optional } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CollectionCustomStructure, @@ -53,7 +55,7 @@ export class SelectFilter implements Filter { /** * Initialize the Filter */ - constructor(protected translate: TranslateService, protected collectionService: CollectionService, protected isMultipleSelect = true) { + constructor(@Optional() protected translate: TranslateService, protected collectionService: CollectionService, protected isMultipleSelect = true) { // default options used by this Filter, user can overwrite any of these by passing "otions" const options: MultipleSelectOption = { autoAdjustDropHeight: true, @@ -92,9 +94,9 @@ export class SelectFilter implements Filter { options.single = false; options.okButton = true; options.addTitle = true; // show tooltip of all selected items while hovering the filter - options.countSelected = this.translate.instant('X_OF_Y_SELECTED'); - options.allSelected = this.translate.instant('ALL_SELECTED'); - options.selectAllText = this.translate.instant('SELECT_ALL'); + options.countSelected = this.translate && this.translate.instant && this.translate.instant('X_OF_Y_SELECTED') || Constants.TEXT_X_OF_Y_SELECTED; + options.allSelected = this.translate && this.translate.instant && this.translate.instant('ALL_SELECTED') || Constants.TEXT_ALL_SELECTED; + options.selectAllText = this.translate && this.translate.instant && this.translate.instant('SELECT_ALL') || Constants.TEXT_SELECT_ALL; options.selectAllDelimiter = ['', '']; // remove default square brackets of default text "[Select All]" => "Select All" } @@ -330,56 +332,58 @@ export class SelectFilter implements Filter { const sanitizedOptions = this.gridOptions && this.gridOptions.sanitizeHtmlOptions || {}; // collection could be an Array of Strings OR Objects - if (optionCollection.every(x => typeof x === 'string')) { - optionCollection.forEach((option: string) => { - const selected = (searchTerms.findIndex((term) => term === option) >= 0) ? 'selected' : ''; - options += ``; - - // if there's at least 1 search term found, we will add the "filled" class for styling purposes - if (selected) { - this.isFilled = true; - } - }); - } else { - // array of objects will require a label/value pair unless a customStructure is passed - optionCollection.forEach((option: SelectOption) => { - if (!option || (option[this.labelName] === undefined && option.labelKey === undefined)) { - throw new Error(`[select-filter] A collection with value/label (or value/labelKey when using Locale) is required to populate the Select list, for example:: { filter: model: Filters.multipleSelect, collection: [ { value: '1', label: 'One' } ]')`); - } - const labelKey = (option.labelKey || option[this.labelName]) as string; - const selected = (searchTerms.findIndex((term) => term === option[this.valueName]) >= 0) ? 'selected' : ''; - const labelText = ((option.labelKey || this.enableTranslateLabel) && labelKey) ? this.translate.instant(labelKey || ' ') : labelKey; - let prefixText = option[this.labelPrefixName] || ''; - let suffixText = option[this.labelSuffixName] || ''; - let optionLabel = option[this.optionLabel] || ''; - optionLabel = optionLabel.toString().replace(/\"/g, '\''); // replace double quotes by single quotes to avoid interfering with regular html - - // also translate prefix/suffix if enableTranslateLabel is true and text is a string - prefixText = (this.enableTranslateLabel && prefixText && typeof prefixText === 'string') ? this.translate.instant(prefixText || ' ') : prefixText; - suffixText = (this.enableTranslateLabel && suffixText && typeof suffixText === 'string') ? this.translate.instant(suffixText || ' ') : suffixText; - optionLabel = (this.enableTranslateLabel && optionLabel && typeof optionLabel === 'string') ? this.translate.instant(optionLabel || ' ') : optionLabel; - - // add to a temp array for joining purpose and filter out empty text - const tmpOptionArray = [prefixText, labelText, suffixText].filter((text) => text); - let optionText = tmpOptionArray.join(separatorBetweenLabels); - - // if user specifically wants to render html text, he needs to opt-in else it will stripped out by default - // also, the 3rd party lib will saninitze any html code unless it's encoded, so we'll do that - if (isRenderHtmlEnabled) { - // sanitize any unauthorized html tags like script and others - // for the remaining allowed tags we'll permit all attributes - const sanitizedText = DOMPurify.sanitize(optionText, sanitizedOptions); - optionText = htmlEncode(sanitizedText); - } - - // html text of each select option - options += ``; - - // if there's at least 1 search term found, we will add the "filled" class for styling purposes - if (selected) { - this.isFilled = true; - } - }); + if (Array.isArray(optionCollection)) { + if (optionCollection.every(x => typeof x === 'string')) { + optionCollection.forEach((option: string) => { + const selected = (searchTerms.findIndex((term) => term === option) >= 0) ? 'selected' : ''; + options += ``; + + // if there's at least 1 search term found, we will add the "filled" class for styling purposes + if (selected) { + this.isFilled = true; + } + }); + } else { + // array of objects will require a label/value pair unless a customStructure is passed + optionCollection.forEach((option: SelectOption) => { + if (!option || (option[this.labelName] === undefined && option.labelKey === undefined)) { + throw new Error(`[select-filter] A collection with value/label (or value/labelKey when using Locale) is required to populate the Select list, for example:: { filter: model: Filters.multipleSelect, collection: [ { value: '1', label: 'One' } ]')`); + } + const labelKey = (option.labelKey || option[this.labelName]) as string; + const selected = (searchTerms.findIndex((term) => term === option[this.valueName]) >= 0) ? 'selected' : ''; + const labelText = ((option.labelKey || this.enableTranslateLabel) && labelKey) ? this.translate.instant(labelKey || ' ') : labelKey; + let prefixText = option[this.labelPrefixName] || ''; + let suffixText = option[this.labelSuffixName] || ''; + let optionLabel = option[this.optionLabel] || ''; + optionLabel = optionLabel.toString().replace(/\"/g, '\''); // replace double quotes by single quotes to avoid interfering with regular html + + // also translate prefix/suffix if enableTranslateLabel is true and text is a string + prefixText = (this.enableTranslateLabel && prefixText && typeof prefixText === 'string') ? this.translate.instant(prefixText || ' ') : prefixText; + suffixText = (this.enableTranslateLabel && suffixText && typeof suffixText === 'string') ? this.translate.instant(suffixText || ' ') : suffixText; + optionLabel = (this.enableTranslateLabel && optionLabel && typeof optionLabel === 'string') ? this.translate.instant(optionLabel || ' ') : optionLabel; + + // add to a temp array for joining purpose and filter out empty text + const tmpOptionArray = [prefixText, labelText, suffixText].filter((text) => text); + let optionText = tmpOptionArray.join(separatorBetweenLabels); + + // if user specifically wants to render html text, he needs to opt-in else it will stripped out by default + // also, the 3rd party lib will saninitze any html code unless it's encoded, so we'll do that + if (isRenderHtmlEnabled) { + // sanitize any unauthorized html tags like script and others + // for the remaining allowed tags we'll permit all attributes + const sanitizedText = DOMPurify.sanitize(optionText, sanitizedOptions); + optionText = htmlEncode(sanitizedText); + } + + // html text of each select option + options += ``; + + // if there's at least 1 search term found, we will add the "filled" class for styling purposes + if (selected) { + this.isFilled = true; + } + }); + } } return ``; diff --git a/src/app/modules/angular-slickgrid/services/collection.service.ts b/src/app/modules/angular-slickgrid/services/collection.service.ts index 5a0cadfa7..75e02f933 100644 --- a/src/app/modules/angular-slickgrid/services/collection.service.ts +++ b/src/app/modules/angular-slickgrid/services/collection.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Optional } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { CollectionFilterBy, @@ -15,7 +15,7 @@ import { uniqueArray } from './utilities'; @Injectable() export class CollectionService { - constructor(private translate: TranslateService) { } + constructor(@Optional() private translate: TranslateService) { } /** * Filter 1 or more items from a collection @@ -86,6 +86,10 @@ export class CollectionService { * @param enableTranslateLabel */ sortCollection(columnDef: Column, collection: any[], sortByOptions: CollectionSortBy | CollectionSortBy[], enableTranslateLabel?: boolean): any[] { + if (enableTranslateLabel && (!this.translate || !this.translate.instant)) { + throw new Error('[Angular-Slickgrid] requires "ngx-translate" to be installed and configured when the grid option "enableTranslate" is enabled.'); + } + let sortedCollection: any[] = []; if (sortByOptions) { diff --git a/src/app/modules/angular-slickgrid/services/export.service.ts b/src/app/modules/angular-slickgrid/services/export.service.ts index 9206a652d..f8bf61a03 100644 --- a/src/app/modules/angular-slickgrid/services/export.service.ts +++ b/src/app/modules/angular-slickgrid/services/export.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Optional } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { Column, @@ -33,7 +33,7 @@ export class ExportService { onGridBeforeExportToFile = new Subject(); onGridAfterExportToFile = new Subject<{ content?: string; filename: string; format: string; useUtf8WithBom: boolean; }>(); - constructor(private translate: TranslateService) { } + constructor(@Optional() private translate: TranslateService) { } private get datasetIdName(): string { return this._gridOptions && this._gridOptions.datasetIdPropertyName || 'id'; @@ -53,6 +53,10 @@ export class ExportService { init(grid: any, dataView: any): void { this._grid = grid; this._dataView = dataView; + + if (this._gridOptions.enableTranslate && (!this.translate || !this.translate.instant)) { + throw new Error('[Angular-Slickgrid] requires "ngx-translate" to be installed and configured when the grid option "enableTranslate" is enabled.'); + } } /** diff --git a/src/app/modules/angular-slickgrid/services/extension.service.ts b/src/app/modules/angular-slickgrid/services/extension.service.ts index c662a2107..0ef19bed1 100644 --- a/src/app/modules/angular-slickgrid/services/extension.service.ts +++ b/src/app/modules/angular-slickgrid/services/extension.service.ts @@ -3,7 +3,7 @@ import 'slickgrid/plugins/slick.cellrangedecorator'; import 'slickgrid/plugins/slick.cellrangeselector'; import 'slickgrid/plugins/slick.cellselectionmodel'; -import { Injectable } from '@angular/core'; +import { Injectable, Optional } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { Column, @@ -45,8 +45,12 @@ export class ExtensionService { private rowMoveManagerExtension: RowMoveManagerExtension, private rowSelectionExtension: RowSelectionExtension, private sharedService: SharedService, - private translate: TranslateService, - ) { } + @Optional() private translate: TranslateService, + ) { + if (this.sharedService.gridOptions && this.sharedService.gridOptions.enableTranslate && (!this.translate || !this.translate.instant)) { + throw new Error('[Angular-Slickgrid] requires "ngx-translate" to be installed and configured when the grid option "enableTranslate" is enabled.'); + } + } /** Dispose of all the controls & plugins */ dispose() {