diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f0a7e617a6..844cb74855d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,16 @@ All notable changes for each version of this project will be documented in this ### General +- **Touch Gestures (HammerJS)** _(optional)_ + - `HammerModule`, previously exported from `@angular/platform-browser`, is no longer available in Angular 22. Touch gesture support (Slider, Drag & Drop, Carousel swipe, Navigation Drawer) is optional. To enable it, install the `hammerjs` package and add it to the `scripts` array in your project's `angular.json`: + ```bash + npm install hammerjs + ``` + ```json + // angular.json — inside your project's architect.build.options + "scripts": ["./node_modules/hammerjs/hammer.min.js"] + ``` + - `IgxSelectComponent` - The default positioning strategy has changed from the internal overlap strategy to `AutoPositionStrategy`. The dropdown now opens below (or above, if there is not enough space) the input element, consistent with other connected components. - Added `IgxSelectOverlapPositionStrategy` - a new publicly exported strategy that preserves the previous behavior of aligning the selected item's text over the input text. To opt into the previous overlap behavior: diff --git a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts index e7231a943a4..0cee693395d 100644 --- a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts +++ b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.ts @@ -1066,7 +1066,6 @@ export class IgxForOfDirective extends IgxForOfToken node.nodeType === Node.ELEMENT_NODE) || embView.rootNodes[0].nextElementSibling); const view = container.detach(0); - // embView and view both refer to the same collections this.updateTemplateContext(embView.context, i); // Because in Elements the whole parent div (containing data-index) gets removed (possibly due to being disconnected). In Angular it just gets moved. @@ -1092,7 +1091,6 @@ export class IgxForOfDirective extends IgxForOfToken } + + + + diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.ts b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.ts index 4ac8720d03c..108344df8de 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.ts +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.ts @@ -36,6 +36,7 @@ import { IgxIconComponent } from 'igniteui-angular/icon'; import { EntityType, FieldType, IFilteringExpressionsTree, IgxOverlayOutletDirective, flatten, IGridResourceStrings } from 'igniteui-angular/core'; import { IgxPaginatorToken } from 'igniteui-angular/paginator'; import { IgxGridCellMergePipe, IgxGridComponent, IgxGridFilteringPipe, IgxGridSortingPipe, IgxGridUnmergeActivePipe } from 'igniteui-angular/grids/grid'; +import { registerLifecyclePlaceholderElement } from './lifecycle-placeholder-element'; let NEXT_ID = 0; @@ -647,6 +648,9 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti * @hidden */ public override ngOnInit() { + if (this.platform.isBrowser) { + registerLifecyclePlaceholderElement(); + } // this.expansionStatesChange.pipe(takeUntil(this.destroy$)).subscribe((value: Map) => { // const res = Array.from(value.entries()).filter(({1: v}) => v === true).map(([k]) => k); // }); @@ -659,6 +663,26 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti super.ngOnInit(); } + // Event that triggers when element gets connected back to the DOM. + // Used to determine when to reopen a previously closed row editing overlay. + protected onLifecyclePlaceholderConnected(): void { + if (this.rowEditable && this.crudService.rowInEditMode && this.rowEditingOverlay && + this.rowEditingOverlay.collapsed) { + // Row is in edit mode, but overlay is closed - reopen. + this.openRowOverlay(this.crudService.rowInEditMode.id); + } + + } + + // Event that triggers when element gets disconnected from the DOM, for example as a result of virtualization or caching. + // Used to determine when to close the row editing overlay. + protected onLifecyclePlaceholderDisconnected(): void { + if (this.rowEditable && this.crudService.rowInEditMode && this.rowEditingOverlay) { + // disconnected from DOM (possibly cached) & row was in edit mode - close overlay. + this.closeRowEditingOverlay(); + } + } + /** * @hidden */ @@ -1239,15 +1263,15 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti { name: null, fields: filterableFields.map(f => ({ - field: f.field, - dataType: f.dataType, - header: f.header, - editorOptions: f.editorOptions, - filters: f.filters, - pipeArgs: f.pipeArgs, - defaultTimeFormat: f.defaultTimeFormat, - defaultDateTimeFormat: f.defaultDateTimeFormat - })) as FieldType[] + field: f.field, + dataType: f.dataType, + header: f.header, + editorOptions: f.editorOptions, + filters: f.filters, + pipeArgs: f.pipeArgs, + defaultTimeFormat: f.defaultTimeFormat, + defaultDateTimeFormat: f.defaultDateTimeFormat + })) as FieldType[] } ]; @@ -1256,7 +1280,7 @@ export class IgxHierarchicalGridComponent extends IgxHierarchicalGridBaseDirecti this.data[0][rowIsland.key][0] : null; return acc.concat(this.generateChildEntity(rowIsland, childFirstRowData)); } - , []); + , []); } return entities; diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/lifecycle-placeholder-element.ts b/projects/igniteui-angular/grids/hierarchical-grid/src/lifecycle-placeholder-element.ts new file mode 100644 index 00000000000..e22c54aaee2 --- /dev/null +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/lifecycle-placeholder-element.ts @@ -0,0 +1,23 @@ +const LIFECYCLE_PLACEHOLDER_TAG = 'igc-lifecycle-placeholder'; +const LIFECYCLE_CONNECTED_EVENT = 'igcConnected'; +const LIFECYCLE_DISCONNECTED_EVENT = 'igcDisconnected'; + +/** @hidden @internal */ +export function registerLifecyclePlaceholderElement(): void { + if (typeof customElements === 'undefined' || typeof HTMLElement === 'undefined' || + typeof CustomEvent === 'undefined' || customElements.get(LIFECYCLE_PLACEHOLDER_TAG)) { + return; + } + + class LifecyclePlaceholderElement extends HTMLElement { + public connectedCallback(): void { + this.dispatchEvent(new CustomEvent(LIFECYCLE_CONNECTED_EVENT)); + } + + public disconnectedCallback(): void { + this.dispatchEvent(new CustomEvent(LIFECYCLE_DISCONNECTED_EVENT)); + } + } + + customElements.define(LIFECYCLE_PLACEHOLDER_TAG, LifecyclePlaceholderElement); +} diff --git a/skills/igniteui-angular-components/references/directives.md b/skills/igniteui-angular-components/references/directives.md index 5c9df924e12..2470fd8fd73 100644 --- a/skills/igniteui-angular-components/references/directives.md +++ b/skills/igniteui-angular-components/references/directives.md @@ -254,7 +254,14 @@ onDrop(event: IDropDroppedEventArgs) { Key drag events: `(dragStart)`, `(dragMove)`, `(dragEnd)`, `(dragClick)`, `(ghostCreate)`, `(ghostDestroy)`, `(transitioned)`. Key drop events: `(enter)`, `(leave)`, `(over)`, `(dropped)`. -> **NOTE:** For touch-based drag, add `importProvidersFrom(HammerModule)` to `app.config.ts` providers. +> **NOTE (optional):** For touch-based drag, install `hammerjs` and add it to the `scripts` array in `angular.json`. +> ```bash +> npm install hammerjs +> ``` +> ```json +> // angular.json — inside your project's architect.build.options +> "scripts": ["./node_modules/hammerjs/hammer.min.js"] +> ``` ## See Also diff --git a/skills/igniteui-angular-components/references/setup.md b/skills/igniteui-angular-components/references/setup.md index 9b062539dcd..db770c643f0 100644 --- a/skills/igniteui-angular-components/references/setup.md +++ b/skills/igniteui-angular-components/references/setup.md @@ -43,7 +43,17 @@ export const appConfig: ApplicationConfig = { | Provider | Package | Required for | |---|---|---| | `provideAnimations()` | `@angular/platform-browser/animations` | **All overlay and animated components** — Dialog, Combo, Select, Dropdown, Date/Time Picker, Snackbar, Toast, Banner, Navigation Drawer, Carousel, Overlay service | -| `importProvidersFrom(HammerModule)` | `@angular/platform-browser` | OPTIONAL — touch gestures (Slider, Drag & Drop, swipe) | + +> **Touch gestures** (Optional) (Slider, Drag & Drop, swipe) - To enable touch gesture support, install the `hammerjs` package and add it to the `scripts` array in your `angular.json`: +> +> ```bash +> npm install hammerjs +> ``` +> +> ```json +> // angular.json — inside your project's architect.build.options +> "scripts": ["./node_modules/hammerjs/hammer.min.js"] +> ``` > **`provideAnimationsAsync()`** lazy-loads the animations module — prefer it for SSR or when optimizing initial bundle size: > ```typescript diff --git a/src/app/hierarchical-grid/hierarchical-grid.sample.html b/src/app/hierarchical-grid/hierarchical-grid.sample.html index 95a8c73db8a..be466342f07 100644 --- a/src/app/hierarchical-grid/hierarchical-grid.sample.html +++ b/src/app/hierarchical-grid/hierarchical-grid.sample.html @@ -150,12 +150,12 @@

Sample two

- - - +