diff --git a/frameworks/angular-slickgrid/README.md b/frameworks/angular-slickgrid/README.md index 2e0fdaee9..4007cf796 100644 --- a/frameworks/angular-slickgrid/README.md +++ b/frameworks/angular-slickgrid/README.md @@ -67,10 +67,6 @@ export class GridComponent implements OnInit { [dataset]="dataset"> ``` -### Troubleshooting - -> [!WARNING] -> Because of its use of native Custom Event, this project **does not** work well with `strictTemplates`, so please make sure to either disable `strictTemplates` or cast your event as `any` (see this [discussion](https://github.com/ghiscoding/Angular-Slickgrid/discussions/815) for more info) ### Styling Themes @@ -143,7 +139,3 @@ Angular-Slickgrid uses [`ngx-translate`](https://github.com/ngx-translate/core) ### Tested with [Vitest](https://vitest.dev/) (Unit Tests) - [Cypress](https://www.cypress.io/) (E2E Tests) Slickgrid-Universal & Angular-Slickgrid both have **100%** Unit Test Coverage and also every Angular-Slickgrid Examples are fully tested with [Cypress](https://www.cypress.io/) as E2E tests. - -## Troubleshooting Section - -- [`strictTemplates` error](https://ghiscoding.gitbook.io/angular-slickgrid/getting-started/troubleshooting#stricttemplates-error) diff --git a/frameworks/angular-slickgrid/docs/TOC.md b/frameworks/angular-slickgrid/docs/TOC.md index e2d1c636c..1114991b1 100644 --- a/frameworks/angular-slickgrid/docs/TOC.md +++ b/frameworks/angular-slickgrid/docs/TOC.md @@ -36,8 +36,8 @@ ## Events -* [Available events](events/Available-Events.md) -* [On Events](events/Grid-&-DataView-Events.md) +* [Available events](events/available-events.md) +* [On Events](events/grid-and-dataview-events.md) ## Slick Grid/DataView Objects * [Slick Grid/DataView Objects](slick-grid-dataview-objects/slickgrid-dataview-objects.md) diff --git a/frameworks/angular-slickgrid/docs/events/Available-Events.md b/frameworks/angular-slickgrid/docs/events/available-events.md similarity index 97% rename from frameworks/angular-slickgrid/docs/events/Available-Events.md rename to frameworks/angular-slickgrid/docs/events/available-events.md index 83aed5a8c..57c4682a5 100644 --- a/frameworks/angular-slickgrid/docs/events/Available-Events.md +++ b/frameworks/angular-slickgrid/docs/events/available-events.md @@ -101,6 +101,12 @@ handleOnHeaderMenuCommand(e) { - `onHeaderMenuBeforeMenuShow` - `onHeaderMenuAfterMenuShow` +#### Export Services + - `onAfterExportToExcel` + - `onBeforeExportToExcel` + - `onBeforeExportToTextFile` + - `onAfterExportToTextFile` + #### Filter Service - `onBeforeFilterClear` - `onBeforeSearchChange` diff --git a/frameworks/angular-slickgrid/docs/events/Grid-&-DataView-Events.md b/frameworks/angular-slickgrid/docs/events/grid-and-dataview-events.md similarity index 82% rename from frameworks/angular-slickgrid/docs/events/Grid-&-DataView-Events.md rename to frameworks/angular-slickgrid/docs/events/grid-and-dataview-events.md index 551837dea..03a467073 100644 --- a/frameworks/angular-slickgrid/docs/events/Grid-&-DataView-Events.md +++ b/frameworks/angular-slickgrid/docs/events/grid-and-dataview-events.md @@ -179,33 +179,3 @@ export class MyApp { } } ``` - -### Error thrown in the IDE when using `strictTemplates` -You might get some error thrown in your editor by the Angular-Language-Service, the error might 1 of these -```shell -Event onAngularGridCreated is not emitted by any applicable directives nor by angular-slickgrid element -``` -or -```shell -error TS2339: Property 'detail' does not exist on type 'Event'. -``` -There are 3 possible solutions to fix this issue -1. disabled `strictTemplates` -2. define argument type as `Event` to avoid error then later cast it as a `CustomEvent` -```ts -angularGridReady(event: Event) { - this.angularGrid = (event as CustomEvent).detail as AngularGridInstance; -} -``` -3. use `$any()` in the View -```html - - -``` -You can read more on the subject at: -- Stack Overflow question [Cannot use onAngularGridCreated emitter](https://stackoverflow.com/questions/71156193/cannot-use-onangulargridcreated-emitter/71245004#71245004) -- Discussion [#815](https://github.com/ghiscoding/angular-slickgrid/discussions/815) \ No newline at end of file diff --git a/frameworks/angular-slickgrid/oxlintrc-angular.json b/frameworks/angular-slickgrid/oxlintrc-angular.json index 3bf41965e..4455b1011 100644 --- a/frameworks/angular-slickgrid/oxlintrc-angular.json +++ b/frameworks/angular-slickgrid/oxlintrc-angular.json @@ -7,17 +7,7 @@ }, "plugins": ["oxc", "regex", "typescript", "vitest"], "jsPlugins": ["@angular-eslint/eslint-plugin"], - "ignorePatterns": [ - "**/*.spec.ts", - "**/*.cy.ts", - ".angular/*", - "dist/", - "coverage/", - "test/", - "**/environment.*.ts", - "**/grid-remote.component.ts", - "**/public_api.ts" - ], + "ignorePatterns": ["**/*.spec.ts", "**/*.cy.ts", ".angular/*", "dist/", "coverage/", "test/", "**/environment.*.ts", "**/public_api.ts"], "overrides": [ { "files": ["**/*.ts"], diff --git a/frameworks/angular-slickgrid/src/demos/examples/example05.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example05.component.ts index 821f61485..5b2ef4607 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example05.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example05.component.ts @@ -6,6 +6,7 @@ import { AngularSlickgridModule, Filters, OperatorType, + PaginationMetadata, type AngularGridInstance, type Column, type GridOption, @@ -443,7 +444,7 @@ export class Example5Component implements OnInit { return true; } - handleOnBeforePaginationChange(_e: Event) { + handleOnBeforePaginationChange(_e: CustomEvent) { // e.preventDefault(); // return false; return true; diff --git a/frameworks/angular-slickgrid/src/demos/examples/example19-rowdetail.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example19-rowdetail.component.ts index 1ea4580d4..4221a0576 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example19-rowdetail.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example19-rowdetail.component.ts @@ -4,22 +4,25 @@ import { FormsModule } from '@angular/forms'; import type { SlickDataView, SlickGrid } from '../../library'; import type { Example19Component } from './example19.component'; +interface ItemDetail { + rowId: string; + duration: number; + percentComplete: number; + reporter: string; + start: Date; + finish: Date; + effortDriven: boolean; + assignee: string; + title: string; +} + @Component({ styles: ['.detail-label { display: inline-flex; align-items: center; gap: 4px; padding: 4px; }', 'label { font-weight: 600; }'], templateUrl: './example19-rowdetail.component.html', - imports: [FormsModule, DecimalPipe, DatePipe], + imports: [DatePipe, DecimalPipe, FormsModule], }) export class Example19RowDetailComponent { - model!: { - duration: Date; - percentComplete: number; - reporter: string; - start: Date; - finish: Date; - effortDriven: boolean; - assignee: string; - title: string; - }; + model: ItemDetail = {} as ItemDetail; // you also have access to the following objects (it must match the exact property names shown below) addon: any; // row detail addon instance @@ -30,7 +33,7 @@ export class Example19RowDetailComponent { // NOTE that you MUST provide it through the "parentRef" property in your "rowDetail" grid options parentRef!: Example19Component; - alertAssignee(name: string) { + alertAssignee(name?: string) { if (typeof name === 'string') { alert(`Assignee on this task is: ${name.toUpperCase()}`); } else { @@ -38,7 +41,7 @@ export class Example19RowDetailComponent { } } - deleteRow(model: any) { + deleteRow(model: ItemDetail) { if (confirm(`Are you sure that you want to delete ${model.title}?`)) { // you first need to collapse all rows (via the 3rd party addon instance) this.addon.collapseAll(); @@ -50,7 +53,7 @@ export class Example19RowDetailComponent { } } - callParentMethod(model: any) { + callParentMethod(model: ItemDetail) { this.parentRef.showFlashMessage(`We just called Parent Method from the Row Detail Child Component on ${model.title}`); } } diff --git a/frameworks/angular-slickgrid/src/demos/examples/example27.component.html b/frameworks/angular-slickgrid/src/demos/examples/example27.component.html index e342b8e9f..63cff4ca1 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example27.component.html +++ b/frameworks/angular-slickgrid/src/demos/examples/example27.component.html @@ -132,11 +132,9 @@

(onFilterCleared)="hideSpinner()" (onBeforeSortChange)="showSpinner()" (onSortChanged)="hideSpinner()" - (onBeforeToggleTreeCollapse)="showSpinner()" - (onToggle-tree-collapsed)="hideSpinner()" - (onTree-full-toggle-start)="showSpinner()" - (onTree-full-toggle-end)="handleOnTreeFullToggleEnd($event.detail)" - (onTree-item-toggled)="handleOnTreeItemToggled($event.detail)" + (onTreeFullToggleStart)="showSpinner()" + (onTreeFullToggleEnd)="handleOnTreeFullToggleEnd($event.detail)" + (onTreeItemToggled)="handleOnTreeItemToggled($event.detail)" > diff --git a/frameworks/angular-slickgrid/src/demos/examples/example30.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example30.component.ts index d58a653a7..8002196f3 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example30.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example30.component.ts @@ -617,8 +617,8 @@ export class Example30Component implements OnDestroy, OnInit { return false; } - handleItemDeleted(itemId: string) { - console.log('item deleted with id:', itemId); + handleItemDeleted(itemIds: string[]) { + console.log('item deleted with ids:', itemIds); } handleOnBeforeEditCell(e: Event, args: any) { diff --git a/frameworks/angular-slickgrid/src/demos/examples/example32.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example32.component.ts index 3b103fa1e..3e5d485ce 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example32.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example32.component.ts @@ -17,35 +17,11 @@ import { type GridOption, type LongTextEditorOption, type SearchTerm, - type SlickGrid, type VanillaCalendarOption, } from '../../library'; const URL_COUNTRIES_COLLECTION = 'assets/data/countries.json'; -/** - * Check if the current item (cell) is editable or not - * @param {*} dataContext - item data context object - * @param {*} columnDef - column definition - * @param {*} grid - slickgrid grid object - * @returns {boolean} isEditable - */ -function checkItemIsEditable(dataContext: any, columnDef: Column, grid: SlickGrid) { - const gridOptions = grid && grid.getOptions && grid.getOptions(); - const hasEditor = columnDef.editor; - const isGridEditable = gridOptions.editable; - let isEditable = !!(isGridEditable && hasEditor); - - if (dataContext && columnDef && gridOptions && gridOptions.editable) { - switch (columnDef.id) { - case 'finish': - isEditable = !!dataContext?.completed; - break; - } - } - return isEditable; -} - const customEditableInputFormatter: Formatter = (_row, _cell, value, columnDef, _dataContext, grid) => { const gridOptions = grid && grid.getOptions && grid.getOptions(); const isEditableLine = gridOptions.editable && columnDef.editor; @@ -607,44 +583,6 @@ export class Example32Component implements OnInit { return tmpArray; } - handleValidationError(_e: Event, args: any) { - if (args.validationResults) { - alert(args.validationResults.msg); - } - return false; - } - - handleItemDeleted(_e: Event, args: any) { - console.log('item deleted with id:', args.itemId); - } - - handleOnBeforeEditCell(e: Event, args: any) { - const { column, item, grid } = args; - - if (column && item) { - if (!checkItemIsEditable(item, column, grid)) { - e.preventDefault(); // OR eventData.preventDefault(); - return false; - } - } - return false; - } - - handleOnCellChange(_e: Event, args: any) { - const dataContext = args?.item; - - // when the field "completed" changes to false, we also need to blank out the "finish" date - if (dataContext && !dataContext.completed) { - dataContext.finish = null; - this.angularGrid.gridService.updateItem(dataContext); - } - } - - handlePaginationChanged() { - this.removeAllUnsavedStylingFromCell(); - this.renderUnsavedStylingOnAllVisibleCells(); - } - handleDefaultResizeColumns() { // just for demo purposes, set it back to its original width const columns = this.angularGrid.slickGrid.getColumns() as Column[]; diff --git a/frameworks/angular-slickgrid/src/demos/examples/example47-rowdetail.component.ts b/frameworks/angular-slickgrid/src/demos/examples/example47-rowdetail.component.ts index 720bbd4b2..d537220d4 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/example47-rowdetail.component.ts +++ b/frameworks/angular-slickgrid/src/demos/examples/example47-rowdetail.component.ts @@ -7,7 +7,7 @@ import { showToast } from './utilities'; interface ItemDetail { id: number; - duration: Date; + duration: number; percentComplete: number; reporter: string; start: Date; @@ -34,7 +34,7 @@ export class Example47RowDetailComponent { // NOTE that you MUST provide it through the "parentRef" property in your "rowDetail" grid options parentRef!: Example47Component; - alertAssignee(name: string) { + alertAssignee(name?: string) { if (typeof name === 'string') { alert(`Assignee on this task is: ${name.toUpperCase()}`); } else { diff --git a/frameworks/angular-slickgrid/src/demos/examples/grid-remote.component.html b/frameworks/angular-slickgrid/src/demos/examples/grid-remote.component.html deleted file mode 100644 index d9d7af995..000000000 --- a/frameworks/angular-slickgrid/src/demos/examples/grid-remote.component.html +++ /dev/null @@ -1,70 +0,0 @@ -
-

- Example 18: Octopart Catalog Search - Remote Model Plugin - - - code - - -

-
- This example demonstrates how to use "slick.remotemodel.js" or any Remote implementation through an external Remote Service -
    -
  • - Your browser (Chrome) might block access to the Octopart query, if you get "block content" then just unblock it or try with - different browser like Firefox or Edge -
  • -
  • If the demo throws some errors, try again later (there's a limit per day).
  • -
  • - Uses slick.remotemodel.js - which is hooked up to load search results from Octopart, but can easily be extended to support any JSONP-compatible backend that - accepts paging parameters. -
  • -
  • - This demo implements a custom DataView, however please note that you are on your own to implement all necessary DataView methods for - Sorting, Filtering, etc... -
  • -
  • - Soure code for this example is available - here -
  • -
-
- -
- - -
- - - - - - - -
diff --git a/frameworks/angular-slickgrid/src/demos/examples/grid-remote.component.ts b/frameworks/angular-slickgrid/src/demos/examples/grid-remote.component.ts deleted file mode 100644 index 941e8ebff..000000000 --- a/frameworks/angular-slickgrid/src/demos/examples/grid-remote.component.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { Component, type OnDestroy, type OnInit } from '@angular/core'; -import { SlickEventHandler, type AngularGridInstance, type Column, type Formatter, type GridOption } from '../../library'; - -const brandFormatter: Formatter = (_row, _cell, _value, _columnDef, dataContext) => { - return (dataContext && dataContext.brand && dataContext.brand.name) || ''; -}; - -const mpnFormatter: Formatter = (_row, _cell, _value, _columnDef, dataContext) => { - let link = ''; - if (dataContext && dataContext.octopart_url && dataContext.mpn) { - link = `${dataContext.mpn}`; - } - return link; -}; - -@Component({ - templateUrl: './grid-remote.component.html', - standalone: false, -}) -export class GridRemoteComponent implements OnDestroy, OnInit { - private _eventHandler: any = new SlickEventHandler(); - angularGrid!: AngularGridInstance; - columnDefinitions!: Column[]; - customDataView: any; - gridObj: any; - gridOptions!: GridOption; - dataset = []; - loaderDataView: any; - loading = false; // spinner when loading data - search = ''; - - constructor() { - // this.loaderDataView = new Slick.Data.RemoteModel(); - // this.customDataView = this.loaderDataView && this.loaderDataView.data; - } - - angularGridReady(angularGrid: AngularGridInstance) { - this.angularGrid = angularGrid; - this.gridObj = angularGrid.slickGrid; // grid object - this.loaderDataView?.setSort('score', -1); - this.gridObj?.setSortColumn('score', false); - - // notify of a change to preload the first page - this.gridObj.onViewportChanged.notify(); - } - - ngOnDestroy() { - // unsubscribe all SlickGrid events - this._eventHandler.unsubscribeAll(); - } - - ngOnInit(): void { - this.defineGrid(); - this.hookAllLoaderEvents(); - - // set default search - // this.search = 'switch'; - // this.loaderDataView.setSearch(this.search); - } - - defineGrid() { - this.columnDefinitions = [ - { id: 'mpn', name: 'MPN', field: 'mpn', formatter: mpnFormatter, width: 100, sortable: true }, - { id: 'brand', name: 'Brand', field: 'brand.name', formatter: brandFormatter, width: 100, sortable: true }, - { id: 'short_description', name: 'Description', field: 'short_description', width: 520 }, - ]; - - this.gridOptions = { - enableAutoResize: true, - autoResize: { - container: '#demo-container', - rightPadding: 10, - }, - enableCellNavigation: true, - enableColumnReorder: false, - enableGridMenu: false, - multiColumnSort: false, - }; - } - - hookAllLoaderEvents() { - if ( - this._eventHandler && - this._eventHandler.subscribe && - this.loaderDataView && - this.loaderDataView.onDataLoading && - this.loaderDataView.onDataLoaded - ) { - this._eventHandler.subscribe(this.loaderDataView.onDataLoading, (_e: Event, _args: any) => { - this.loading = true; - }); - - this._eventHandler.subscribe(this.loaderDataView.onDataLoaded, (_e: Event, args: any) => { - if (args && this.gridObj && this.gridObj.invalidateRow && this.gridObj.updateRowCount && this.gridObj.render) { - for (let i = args.from; i <= args.to; i++) { - this.gridObj.invalidateRow(i); - } - this.gridObj.updateRowCount(); - this.gridObj.render(); - this.loading = false; - } - }); - } - } - - onSort(_e: Event, args: any) { - if (this.gridObj && this.gridObj.getViewport && this.loaderDataView && this.loaderDataView.ensureData && this.loaderDataView.setSort) { - const vp = this.gridObj.getViewport(); - if (args && args.sortCol && args.sortCol.field) { - this.loaderDataView.setSort(args.sortCol.field, args.sortAsc ? 1 : -1); - } - this.loaderDataView.ensureData(vp.top, vp.bottom); - } - } - - onViewportChanged() { - if (this.gridObj && this.gridObj.getViewport && this.loaderDataView && this.loaderDataView.ensureData) { - const vp = this.gridObj.getViewport(); - this.loaderDataView.ensureData(vp.top, vp.bottom); - } - } - - searchChanged(newValue: string) { - if ( - newValue && - this.gridObj && - this.gridObj.getViewport && - this.loaderDataView && - this.loaderDataView.ensureData && - this.loaderDataView.setSearch - ) { - const vp = this.gridObj.getViewport(); - this.loaderDataView.setSearch(newValue); - this.loaderDataView.ensureData(vp.top, vp.bottom); - } - } -} diff --git a/frameworks/angular-slickgrid/src/demos/examples/swt-common-grid-test.component.html b/frameworks/angular-slickgrid/src/demos/examples/swt-common-grid-test.component.html index a3b1ac5d6..0c78d674d 100644 --- a/frameworks/angular-slickgrid/src/demos/examples/swt-common-grid-test.component.html +++ b/frameworks/angular-slickgrid/src/demos/examples/swt-common-grid-test.component.html @@ -29,8 +29,8 @@

diff --git a/frameworks/angular-slickgrid/src/library/components/__tests__/angular-slickgrid.component.spec.ts b/frameworks/angular-slickgrid/src/library/components/__tests__/angular-slickgrid.component.spec.ts index 7b326fb72..e31c90303 100644 --- a/frameworks/angular-slickgrid/src/library/components/__tests__/angular-slickgrid.component.spec.ts +++ b/frameworks/angular-slickgrid/src/library/components/__tests__/angular-slickgrid.component.spec.ts @@ -379,32 +379,35 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = nativeElement: divContainer, } as ElementRef; - component = new AngularSlickgridComponent( - angularUtilServiceStub, - mockAppRef, - mockChangeDetectorRef, - containerService, - mockElementRef, - translate as unknown as TranslateService, - translaterService as unknown as TranslaterService, - {} as GridOption, - { - backendUtilityService: backendUtilityServiceStub, - collectionService: collectionServiceStub, - extensionService: extensionServiceStub, - extensionUtility: mockExtensionUtility, - eventPubSubService, - filterService: filterServiceStub, - gridEventService: gridEventServiceStub, - gridService: gridServiceStub, - gridStateService: gridStateServiceStub, - headerGroupingService: headerGroupingServiceStub, - resizerService: resizerServiceStub, - paginationService: paginationServiceStub, - sharedService, - sortService: sortServiceStub, - treeDataService: treeDataServiceStub, - } + component = TestBed.runInInjectionContext( + () => + new AngularSlickgridComponent( + angularUtilServiceStub, + mockAppRef, + mockChangeDetectorRef, + containerService, + mockElementRef, + translate as unknown as TranslateService, + translaterService as unknown as TranslaterService, + {} as GridOption, + { + backendUtilityService: backendUtilityServiceStub, + collectionService: collectionServiceStub, + extensionService: extensionServiceStub, + extensionUtility: mockExtensionUtility, + eventPubSubService, + filterService: filterServiceStub, + gridEventService: gridEventServiceStub, + gridService: gridServiceStub, + gridStateService: gridStateServiceStub, + headerGroupingService: headerGroupingServiceStub, + resizerService: resizerServiceStub, + paginationService: paginationServiceStub, + sharedService, + sortService: sortServiceStub, + treeDataService: treeDataServiceStub, + } + ) ); component.gridId = 'grid1'; @@ -423,32 +426,35 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () = }); it('should provide the gridService lazily', () => { - const instance = new AngularSlickgridComponent( - angularUtilServiceStub, - mockAppRef, - mockChangeDetectorRef, - containerService, - mockElementRef, - translate as unknown as TranslateService, - translaterService as unknown as TranslaterService, - {} as GridOption, - { - backendUtilityService: backendUtilityServiceStub, - collectionService: collectionServiceStub, - extensionService: undefined, - extensionUtility: mockExtensionUtility, - eventPubSubService, - filterService: filterServiceStub, - gridEventService: gridEventServiceStub, - gridService: gridServiceStub, - gridStateService: gridStateServiceStub, - headerGroupingService: headerGroupingServiceStub, - resizerService: resizerServiceStub, - paginationService: paginationServiceStub, - sharedService, - sortService: sortServiceStub, - treeDataService: treeDataServiceStub, - } + const instance = TestBed.runInInjectionContext( + () => + new AngularSlickgridComponent( + angularUtilServiceStub, + mockAppRef, + mockChangeDetectorRef, + containerService, + mockElementRef, + translate as unknown as TranslateService, + translaterService as unknown as TranslaterService, + {} as GridOption, + { + backendUtilityService: backendUtilityServiceStub, + collectionService: collectionServiceStub, + extensionService: undefined, + extensionUtility: mockExtensionUtility, + eventPubSubService, + filterService: filterServiceStub, + gridEventService: gridEventServiceStub, + gridService: gridServiceStub, + gridStateService: gridStateServiceStub, + headerGroupingService: headerGroupingServiceStub, + resizerService: resizerServiceStub, + paginationService: paginationServiceStub, + sharedService, + sortService: sortServiceStub, + treeDataService: treeDataServiceStub, + } + ) ); expect(instance).toBeTruthy(); diff --git a/frameworks/angular-slickgrid/src/library/components/angular-slickgrid-outputs.interface.ts b/frameworks/angular-slickgrid/src/library/components/angular-slickgrid-outputs.interface.ts new file mode 100644 index 000000000..756dd26da --- /dev/null +++ b/frameworks/angular-slickgrid/src/library/components/angular-slickgrid-outputs.interface.ts @@ -0,0 +1,239 @@ +import type { + Column, + ColumnSort, + CurrentFilter, + CurrentSorter, + DragRowMove, + ExportTextDownloadOption, + GridMenuCommandItemCallbackArgs, + GridMenuEventWithElementCallbackArgs, + GridSize, + GridStateChange, + HeaderButtonOnCommandArgs, + HeaderMenuCommandItemCallbackArgs, + MenuCommandItemCallbackArgs, + MenuFromCellCallbackArgs, + MenuOptionItemCallbackArgs, + OnActiveCellChangedEventArgs, + OnAddNewRowEventArgs, + OnAutosizeColumnsEventArgs, + OnBeforeAppendCellEventArgs, + OnBeforeCellEditorDestroyEventArgs, + OnBeforeColumnsResizeEventArgs, + OnBeforeEditCellEventArgs, + OnBeforeFooterRowCellDestroyEventArgs, + OnBeforeHeaderCellDestroyEventArgs, + OnBeforeHeaderRowCellDestroyEventArgs, + OnBeforeSetColumnsEventArgs, + OnCellChangeEventArgs, + OnCellCssStylesChangedEventArgs, + OnClickEventArgs, + OnColumnsChangedArgs, + OnColumnsDragEventArgs, + OnColumnsReorderedEventArgs, + OnColumnsResizeDblClickEventArgs, + OnColumnsResizedEventArgs, + OnCompositeEditorChangeEventArgs, + OnDblClickEventArgs, + OnDragReplaceCellsEventArgs, + OnFooterClickEventArgs, + OnFooterContextMenuEventArgs, + OnFooterRowCellRenderedEventArgs, + OnGroupCollapsedEventArgs, + OnGroupExpandedEventArgs, + OnHeaderCellRenderedEventArgs, + OnHeaderClickEventArgs, + OnHeaderContextMenuEventArgs, + OnHeaderMouseEventArgs, + OnHeaderRowCellRenderedEventArgs, + OnKeyDownEventArgs, + OnRenderedEventArgs, + OnRowCountChangedEventArgs, + OnRowsChangedEventArgs, + OnRowsOrCountChangedEventArgs, + OnScrollEventArgs, + OnSelectedRowIdsChangedEventArgs, + OnSelectedRowsChangedEventArgs, + OnSetItemsCalledEventArgs, + OnSetOptionsEventArgs, + OnValidationErrorEventArgs, + PaginationMetadata, + PagingInfo, + SingleColumnSort, + SlickDataView, + SlickGrid, + SlickRange, + TreeToggleStateChange, +} from '@slickgrid-universal/common'; +import type { AngularGridInstance } from '../models/index'; + +/** + * Generic type for wrapping event output with detail property + * Used for typed Angular output() signals that need both eventData and args + * Extends CustomEvent for compatibility with event handlers + * @template T - The event function type from AngularSlickgridOutputs interface + */ +export type SlickEventOutput any> = CustomEvent<{ + eventData: any; + args: Parameters[0]; +}>; + +/** + * Generic type for wrapping simple event output with detail property + * Extends CustomEvent for compatibility with event handlers + * @template T - The event function type from AngularSlickgridOutputs interface + */ +export type RegularEventOutput any> = CustomEvent[0]>; + +/** + * Angular-Slickgrid Output Events Interface + * Defines all typed output signals for strict template type checking in Angular 17+ + * These are automatically managed by the AngularSlickgridComponent and should be used in templates + * + * @example + * ```html + * + * ``` + */ +export interface AngularSlickgridOutputs { + // SlickGrid Events + onActiveCellChanged: (e: OnActiveCellChangedEventArgs) => void; + onActiveCellPositionChanged: (e: { grid: SlickGrid }) => void; + onAddNewRow: (e: OnAddNewRowEventArgs) => void; + onAutosizeColumns: (e: OnAutosizeColumnsEventArgs) => void; + onBeforeAppendCell: (e: OnBeforeAppendCellEventArgs) => void; + onBeforeSearchChange: (e: OnCellChangeEventArgs) => boolean | void; + onBeforeCellEditorDestroy: (e: OnBeforeCellEditorDestroyEventArgs) => void; + onBeforeColumnsResize: (e: OnBeforeColumnsResizeEventArgs) => void; + onBeforeDestroy: (e: { grid: SlickGrid }) => void; + onBeforeEditCell: (e: OnBeforeEditCellEventArgs) => void; + onBeforeHeaderCellDestroy: (e: OnBeforeHeaderCellDestroyEventArgs) => void; + onBeforeHeaderRowCellDestroy: (e: OnBeforeHeaderRowCellDestroyEventArgs) => void; + onBeforeFooterRowCellDestroy: (e: OnBeforeFooterRowCellDestroyEventArgs) => void; + onBeforeSetColumns: (e: OnBeforeSetColumnsEventArgs) => void; + onBeforeSort: (e: SingleColumnSort) => boolean | void; + onCellChange: (e: OnCellChangeEventArgs) => void; + onCellCssStylesChanged: (e: OnCellCssStylesChangedEventArgs) => void; + onClick: (e: OnClickEventArgs) => void; + onColumnsDrag: (e: OnColumnsDragEventArgs) => void; + onColumnsReordered: (e: OnColumnsReorderedEventArgs) => void; + onColumnsResized: (e: OnColumnsResizedEventArgs) => void; + onColumnsResizeDblClick: (e: OnColumnsResizeDblClickEventArgs) => void; + onCompositeEditorChange: (e: OnCompositeEditorChangeEventArgs) => void; + onContextMenu: (e: { grid: SlickGrid }) => void; + onDrag: (e: DragRowMove) => void; + onDragEnd: (e: DragRowMove) => void; + onDragInit: (e: DragRowMove) => void; + onDragStart: (e: DragRowMove) => void; + onDragReplaceCells: (e: OnDragReplaceCellsEventArgs) => void; + onDblClick: (e: OnDblClickEventArgs) => void; + onFooterContextMenu: (e: OnFooterContextMenuEventArgs) => void; + onFooterRowCellRendered: (e: OnFooterRowCellRenderedEventArgs) => void; + onHeaderCellRendered: (e: OnHeaderCellRenderedEventArgs) => void; + onFooterClick: (e: OnFooterClickEventArgs) => void; + onHeaderClick: (e: OnHeaderClickEventArgs) => void; + onHeaderContextMenu: (e: OnHeaderContextMenuEventArgs) => void; + onHeaderMouseEnter: (e: OnHeaderMouseEventArgs) => void; + onHeaderMouseLeave: (e: OnHeaderMouseEventArgs) => void; + onHeaderRowCellRendered: (e: OnHeaderRowCellRenderedEventArgs) => void; + onHeaderRowMouseEnter: (e: OnHeaderMouseEventArgs) => void; + onHeaderRowMouseLeave: (e: OnHeaderMouseEventArgs) => void; + onKeyDown: (e: OnKeyDownEventArgs) => void; + onMouseEnter: (e: { grid: SlickGrid }) => void; + onMouseLeave: (e: { grid: SlickGrid }) => void; + onValidationError: (e: OnValidationErrorEventArgs) => void; + onViewportChanged: (e: { grid: SlickGrid }) => void; + onRendered: (e: OnRenderedEventArgs) => void; + onSelectedRowsChanged: (e: OnSelectedRowsChangedEventArgs) => void; + onSetOptions: (e: OnSetOptionsEventArgs) => void; + onScroll: (e: OnScrollEventArgs) => void; + onSort: (e: SingleColumnSort) => void; + + // SlickDataView Events + onBeforePagingInfoChanged: (e: PagingInfo) => void; + onGroupExpanded: (e: OnGroupExpandedEventArgs) => void; + onGroupCollapsed: (e: OnGroupCollapsedEventArgs) => void; + onPagingInfoChanged: (e: PagingInfo) => void; + onRowCountChanged: (e: OnRowCountChangedEventArgs) => void; + onRowsChanged: (e: OnRowsChangedEventArgs) => void; + onRowsOrCountChanged: (e: OnRowsOrCountChangedEventArgs) => void; + onSetItemsCalled: (e: OnSetItemsCalledEventArgs) => void; + + // other Slick Events + onAfterMenuShow: (e: MenuFromCellCallbackArgs) => void; + onBeforeMenuClose: (e: MenuFromCellCallbackArgs) => void; + onBeforeMenuShow: (e: MenuFromCellCallbackArgs) => void; + onColumnsChanged: (e: OnColumnsChangedArgs) => void; + onCommand: (e: MenuCommandItemCallbackArgs | MenuOptionItemCallbackArgs) => void; + onGridMenuColumnsChanged: (e: OnColumnsChangedArgs) => void; + onMenuClose: (e: GridMenuEventWithElementCallbackArgs) => void; + onCopyCells: (e: { ranges: SlickRange[] }) => void; + onCopyCancelled: (e: { ranges: SlickRange[] }) => void; + onPasteCells: (e: { ranges: SlickRange[] }) => void; + onBeforePasteCell: (e: { cell: number; row: number; item: any; columnDef: Column; value: any }) => void; + + // Slickgrid-Universal Events + onAfterExportToExcel: (e: { filename: string; mimeType: string }) => void; + onBeforeExportToExcel: (e: boolean) => void; + onBeforeExportToTextFile?: (e: boolean) => void; + onAfterExportToTextFile?: (e: ExportTextDownloadOption) => void; + onBeforeFilterChange: (e: CurrentFilter[]) => void; + onBeforeFilterClear: (e: { columnId: string } | boolean) => void; + onBeforeSortChange: (e: Array) => void; + onContextMenuClearGrouping: () => void; + onContextMenuCollapseAllGroups: () => void; + onContextMenuExpandAllGroups: () => void; + onOptionSelected: (e: MenuCommandItemCallbackArgs | MenuOptionItemCallbackArgs) => void; + onColumnPickerColumnsChanged: (e: OnColumnsChangedArgs) => void; + onGridMenuMenuClose: (e: GridMenuEventWithElementCallbackArgs) => void; + onGridMenuBeforeMenuShow: (e: GridMenuEventWithElementCallbackArgs) => void; + onGridMenuAfterMenuShow: (e: GridMenuEventWithElementCallbackArgs) => void; + onGridMenuClearAllPinning: () => void; + onGridMenuClearAllFilters: () => void; + onGridMenuClearAllSorting: () => void; + onGridMenuCommand: (e: GridMenuCommandItemCallbackArgs) => void; + onHeaderButtonCommand: (e: HeaderButtonOnCommandArgs) => void; + onHeaderMenuCommand: (e: MenuCommandItemCallbackArgs) => void; + onHeaderMenuColumnResizeByContent: (e: { columnId: string }) => void; + onHeaderMenuBeforeMenuShow: (e: HeaderMenuCommandItemCallbackArgs) => void; + onHeaderMenuAfterMenuShow: (e: HeaderMenuCommandItemCallbackArgs) => void; + onHideColumns: (e: { columns: Column[]; hiddenColumn: Column[] }) => void; + onItemsAdded: (e: any[]) => void; + onItemsDeleted: (e: any[]) => void; + onItemsUpdated: (e: any[]) => void; + onItemsUpserted: (e: any[]) => void; + onFullResizeByContentRequested: (e: { caller: string }) => void; + onGridStateChanged: (e: GridStateChange) => void; + onBeforePaginationChange: (e: PaginationMetadata) => boolean | void; + onPaginationChanged: (e: PaginationMetadata) => void; + onPaginationRefreshed: (e: PaginationMetadata) => void; + onPaginationVisibilityChanged: (e: { visible: boolean }) => void; + onPaginationSetCursorBased: (e: { isCursorBased: boolean }) => void; + onGridBeforeResize: () => void; + onGridAfterResize: (e: GridSize | undefined) => void; + onBeforeResizeByContent: () => void; + onAfterResizeByContent: (e: { + readItemCount: number; + calculateColumnWidths: { [x: string]: number | undefined; [x: number]: number | undefined }; + }) => void; + onSelectedRowIdsChanged: (e: OnSelectedRowIdsChangedEventArgs) => void; + onSortCleared: (e: boolean) => void; + onFilterChanged: (e: CurrentFilter[]) => void; + onFilterCleared: (e: boolean) => void; + onSortChanged: (e: CurrentSorter[]) => void; + onTreeItemToggled: (e: TreeToggleStateChange) => void; + onTreeFullToggleEnd: (e: TreeToggleStateChange) => void; + onTreeFullToggleStart: (e: TreeToggleStateChange) => void; + + // Angular-Slickgrid specific events + onBeforeGridCreate: (e: boolean) => void; + onGridCreated: (e: SlickGrid) => void; + onDataviewCreated: (e: SlickDataView) => void; + onAngularGridCreated: (e: AngularGridInstance) => void; + onBeforeGridDestroy: (e: SlickGrid) => void; + onAfterGridDestroyed: (e: boolean) => void; + onLanguageChange: (lang: string) => void; +} diff --git a/frameworks/angular-slickgrid/src/library/components/angular-slickgrid.component.ts b/frameworks/angular-slickgrid/src/library/components/angular-slickgrid.component.ts index 47220e577..4d5bf495a 100644 --- a/frameworks/angular-slickgrid/src/library/components/angular-slickgrid.component.ts +++ b/frameworks/angular-slickgrid/src/library/components/angular-slickgrid.component.ts @@ -9,6 +9,7 @@ import { Input, Optional, Output, + output, type AfterViewInit, type OnDestroy, type TemplateRef, @@ -71,10 +72,10 @@ import { Constants } from '../constants'; import { SlickRowDetailView } from '../extensions/slickRowDetailView'; import { GlobalGridOptions } from '../global-grid-options'; import type { AngularGridInstance, ExternalTestingDependencies, GridOption } from '../models/index'; -// Services import { AngularUtilService } from '../services/angularUtil.service'; import { ContainerService } from '../services/container.service'; import { TranslaterService } from '../services/translater.service'; +import type { AngularSlickgridOutputs, RegularEventOutput, SlickEventOutput } from './angular-slickgrid-outputs.interface'; const WARN_NO_PREPARSE_DATE_SIZE = 10000; // data size to warn user when pre-parse isn't enabled @@ -179,6 +180,139 @@ export class AngularSlickgridComponent implements AfterViewInit, On // are synched on user's side as well (RowMove, RowDetail, RowSelections) @Output() columnsChange = new EventEmitter(true); + // SlickGrid events + onActiveCellChanged = output>(); + onActiveCellPositionChanged = output>(); + onAddNewRow = output>(); + onAutosizeColumns = output>(); + onBeforeAppendCell = output>(); + onBeforeSearchChange = output>(); + onBeforeCellEditorDestroy = output>(); + onBeforeColumnsResize = output>(); + onBeforeDestroy = output>(); + onBeforeEditCell = output>(); + onBeforeHeaderCellDestroy = output>(); + onBeforeHeaderRowCellDestroy = output>(); + onBeforeFooterRowCellDestroy = output>(); + onBeforeSetColumns = output>(); + onBeforeSort = output>(); + onCellChange = output>(); + onCellCssStylesChanged = output>(); + onClick = output>(); + onColumnsDrag = output>(); + onColumnsReordered = output>(); + onColumnsResized = output>(); + onColumnsResizeDblClick = output>(); + onCompositeEditorChange = output>(); + onContextMenu = output>(); + onDrag = output>(); + onDragEnd = output>(); + onDragInit = output>(); + onDragStart = output>(); + onDragReplaceCells = output>(); + onDblClick = output>(); + onFooterContextMenu = output>(); + onFooterRowCellRendered = output>(); + onHeaderCellRendered = output>(); + onFooterClick = output>(); + onHeaderClick = output>(); + onHeaderContextMenu = output>(); + onHeaderMouseEnter = output>(); + onHeaderMouseLeave = output>(); + onHeaderRowCellRendered = output>(); + onHeaderRowMouseEnter = output>(); + onHeaderRowMouseLeave = output>(); + onKeyDown = output>(); + onMouseEnter = output>(); + onMouseLeave = output>(); + onValidationError = output>(); + onViewportChanged = output>(); + onRendered = output>(); + onSelectedRowsChanged = output>(); + onSetOptions = output>(); + onScroll = output>(); + onSort = output>(); + + // DataView events + onBeforePagingInfoChanged = output>(); + onGroupExpanded = output>(); + onGroupCollapsed = output>(); + onPagingInfoChanged = output>(); + onRowCountChanged = output>(); + onRowsChanged = output>(); + onRowsOrCountChanged = output>(); + onSelectedRowIdsChanged = output>(); + onSetItemsCalled = output>(); + + // other Slick Events + onAfterMenuShow = output>(); + onBeforeMenuClose = output>(); + onBeforeMenuShow = output>(); + onColumnsChanged = output>(); + onCommand = output>(); + onGridMenuColumnsChanged = output>(); + onMenuClose = output>(); + onCopyCells = output>(); + onCopyCancelled = output>(); + onPasteCells = output>(); + onBeforePasteCell = output>(); + + // Slickgrid-Universal events + onAfterExportToExcel = output>(); + onBeforeExportToExcel = output>(); + onBeforeFilterChange = output>(); + onBeforeFilterClear = output>(); + onBeforeSortChange = output>(); + onContextMenuClearGrouping = output>(); + onContextMenuCollapseAllGroups = output>(); + onContextMenuExpandAllGroups = output>(); + onOptionSelected = output>(); + onColumnPickerColumnsChanged = output>(); + onGridMenuMenuClose = output>(); + onGridMenuBeforeMenuShow = output>(); + onGridMenuAfterMenuShow = output>(); + onGridMenuClearAllPinning = output>(); + onGridMenuClearAllFilters = output>(); + onGridMenuClearAllSorting = output>(); + onGridMenuCommand = output>(); + onHeaderButtonCommand = output>(); + onHeaderMenuCommand = output>(); + onHeaderMenuColumnResizeByContent = output>(); + onHeaderMenuBeforeMenuShow = output>(); + onHeaderMenuAfterMenuShow = output>(); + onHideColumns = output>(); + onItemsAdded = output>(); + onItemsDeleted = output>(); + onItemsUpdated = output>(); + onItemsUpserted = output>(); + onFullResizeByContentRequested = output>(); + onGridStateChanged = output>(); + onBeforePaginationChange = output>(); + onPaginationChanged = output>(); + onPaginationRefreshed = output>(); + onPaginationVisibilityChanged = output>(); + onPaginationSetCursorBased = output>(); + onGridBeforeResize = output>(); + onGridAfterResize = output>(); + onBeforeResizeByContent = output>(); + onAfterResizeByContent = output>(); + onSortCleared = output>(); + onFilterChanged = output>(); + onFilterCleared = output>(); + onSortChanged = output>(); + onTreeItemToggled = output>(); + onTreeFullToggleEnd = output>(); + onTreeFullToggleStart = output>(); + + // Angular-Slickgrid specific events + onBeforeGridCreate = output>(); + onGridCreated = output>(); + onDataviewCreated = output>(); + onAngularGridCreated = output>(); + onBeforeGridDestroy = output>(); + onAfterGridDestroyed = output>(); + onLanguageChange = output>(); + @Input() get dataset(): any[] { return (this.customDataView ? this.slickGrid?.getData?.() : this.dataView?.getItems()) || []; @@ -273,8 +407,8 @@ export class AngularSlickgridComponent implements AfterViewInit, On return this._registeredResources; } - @ContentChild('slickgridHeader', { static: true }) slickgridHeader?: TemplateRef; - @ContentChild('slickgridFooter', { static: true }) slickgridFooter?: TemplateRef; + @ContentChild('slickgridHeader', { static: true }) slickgridHeader: TemplateRef | null = null; + @ContentChild('slickgridFooter', { static: true }) slickgridFooter: TemplateRef | null = null; constructor( protected readonly angularUtilService: AngularUtilService, @@ -932,7 +1066,7 @@ export class AngularSlickgridComponent implements AfterViewInit, On this.subscriptions.push( this.translate.onLangChange.subscribe(({ lang }) => { // publish event of the same name that Slickgrid-Universal uses on a language change event - this._eventPubSubService.publish('onLanguageChange'); + this._eventPubSubService.publish('onLanguageChange', lang); if (gridOptions.enableTranslate) { this.extensionService.translateAllExtensions(lang); diff --git a/frameworks/angular-slickgrid/src/library/index.ts b/frameworks/angular-slickgrid/src/library/index.ts index 2a4045947..09f6e865f 100644 --- a/frameworks/angular-slickgrid/src/library/index.ts +++ b/frameworks/angular-slickgrid/src/library/index.ts @@ -7,5 +7,6 @@ export { SlickRowDetailView } from './extensions/index'; // components & module export { SlickgridConfig } from './slickgrid-config'; +export type { AngularSlickgridOutputs } from './components/angular-slickgrid-outputs.interface'; export { AngularSlickgridComponent } from './components/angular-slickgrid.component'; export { AngularSlickgridModule } from './modules/angular-slickgrid.module'; diff --git a/frameworks/angular-slickgrid/tsconfig.json b/frameworks/angular-slickgrid/tsconfig.json index 22c269440..98a8468d9 100644 --- a/frameworks/angular-slickgrid/tsconfig.json +++ b/frameworks/angular-slickgrid/tsconfig.json @@ -24,6 +24,12 @@ "angularCompilerOptions": { "compilationMode": "partial", "preserveWhitespaces": true, - "strictMetadataEmit": true + "strictMetadataEmit": true, + "strictTemplates": true, + "extendedDiagnostics": { + "checks": { + "optionalChainNotNullable": "suppress" + } + } } } diff --git a/packages/common/src/interfaces/textExportOption.interface.ts b/packages/common/src/interfaces/textExportOption.interface.ts index 2da149de8..ed93165e3 100644 --- a/packages/common/src/interfaces/textExportOption.interface.ts +++ b/packages/common/src/interfaces/textExportOption.interface.ts @@ -1,6 +1,14 @@ import type { DelimiterType } from '../enums/delimiterType.enum.js'; import type { FileType } from '../enums/fileType.enum.js'; +export interface ExportTextDownloadOption { + filename: string; + content: string; + format: FileType | string; + mimeType: string; + useUtf8WithBom?: boolean; +} + export interface TextExportOption { /** export delimiter, can be (comma, tab, ... or even custom string). */ delimiter?: DelimiterType | string; diff --git a/packages/event-pub-sub/src/eventPubSub.service.ts b/packages/event-pub-sub/src/eventPubSub.service.ts index a456d9851..b66fbee58 100644 --- a/packages/event-pub-sub/src/eventPubSub.service.ts +++ b/packages/event-pub-sub/src/eventPubSub.service.ts @@ -107,7 +107,7 @@ export class EventPubSubService implements BasePubSubService { * Return is a Boolean (from the event dispatch) unless a delay is provided if so we'll return the dispatched event in a Promise with a delayed cycle * The delay is rarely use and is only used when we want to make sure that certain events have the time to execute * and we do this because most framework require a cycle before the binding is processed and binding a spinner end up showing too late - * for example this is used for the following events: onBeforeFilterClear, onBeforeFilterChange, onBeforeToggleTreeCollapse, onBeforeSortChange + * for example this is used for the following events: onBeforeFilterClear, onBeforeFilterChange, onBeforeSortChange * @param {String} event - The event or channel to publish to. * @param {*} data - The data to publish on the channel. * @param {Number} delay - optional argument to delay the publish event diff --git a/packages/text-export/src/textExport.service.ts b/packages/text-export/src/textExport.service.ts index fe149bb71..3bf6c03b7 100644 --- a/packages/text-export/src/textExport.service.ts +++ b/packages/text-export/src/textExport.service.ts @@ -2,6 +2,7 @@ import type { TextExportService as BaseTextExportService, Column, ContainerService, + ExportTextDownloadOption, ExternalResource, FileType, GridOption, @@ -31,14 +32,6 @@ const DEFAULT_EXPORT_OPTIONS: TextExportOption = { useUtf8WithBom: true, }; -interface ExportTextDownloadOption { - filename: string; - content: string; - format: FileType | string; - mimeType: string; - useUtf8WithBom?: boolean; -} - export class TextExportService implements ExternalResource, BaseTextExportService { protected _delimiter = ','; protected _exportQuoteWrapper = '';