diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa685ef730e..9a24c7f85b7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,19 @@
All notable changes for each version of this project will be documented in this file.
+## 21.2.26
+
+### Bug Fixes
+
+- `IgxSnackbarComponent`
+ - The default action button now renders with `type="button"`. Previously, when the snackbar was inside a `form` (for example as part of a grid), it became the default button of the form, so pressing Enter in any input of the form clicked it, which triggered the snackbar action and submitted the form.
+- `IgxQueryBuilderComponent`
+ - The add expression and the group (AND/OR) buttons now render with `type="button"`. Previously, clicking them inside a `form` submitted it. Pressing Enter in the query builder inputs also no longer submits a surrounding `form`.
+- `IgxGridComponent`, `IgxTreeGridComponent`, `IgxHierarchicalGridComponent`, `IgxPivotGridComponent`
+ - Pressing Enter in the grid UI, such as the filtering row, cell and row editors, the toolbar column hiding and pinning, Excel-style filtering and advanced filtering, as well as selecting a date in their date pickers with Enter, no longer submits a surrounding `form`.
+- `IgxAdvancedFilteringDialogComponent`, `IgxColumnActionsComponent`, `IgxPivotDataSelectorComponent`
+ - Pressing Enter in their inputs no longer submits a surrounding `form` when they are rendered outside of the grid, e.g. used standalone, or the advanced filtering dialog opened with custom overlay settings.
+
## 21.2.25
### Bug Fixes
diff --git a/projects/igniteui-angular/core/src/core/utils.spec.ts b/projects/igniteui-angular/core/src/core/utils.spec.ts
index 2a6bb842080..0ae1e117953 100644
--- a/projects/igniteui-angular/core/src/core/utils.spec.ts
+++ b/projects/igniteui-angular/core/src/core/utils.spec.ts
@@ -1,5 +1,5 @@
import { SampleTestData } from 'igniteui-angular/test-utils/sample-test-data.spec';
-import { cloneValue, isObject, isDate } from './utils';
+import { cloneValue, isObject, isDate, preventImplicitSubmission } from './utils';
describe('Utils', () => {
const complexObject = {
@@ -253,4 +253,58 @@ describe('Utils', () => {
expect(isDate(variable)).toBeFalsy();
});
});
+
+ describe('Utils - preventImplicitSubmission() unit tests', () => {
+ let host: HTMLDivElement;
+
+ const dispatchKeydown = (target: Element, init: KeyboardEventInit = {}): boolean => {
+ const event = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true, composed: true, ...init });
+ target.dispatchEvent(event);
+ return event.defaultPrevented;
+ };
+
+ beforeEach(() => {
+ host = document.createElement('div');
+ host.addEventListener('keydown', preventImplicitSubmission);
+ document.body.appendChild(host);
+ });
+
+ afterEach(() => {
+ host.remove();
+ });
+
+ it('should prevent Enter only on a form-owned input which would submit the form', () => {
+ host.innerHTML = '
';
+ const [textInput, fileInput] = Array.from(host.querySelectorAll('form input'));
+
+ expect(dispatchKeydown(textInput)).toBeTrue();
+ expect(dispatchKeydown(fileInput)).toBeFalse();
+ expect(dispatchKeydown(host.querySelector('#noForm'))).toBeFalse();
+ });
+
+ it('should not prevent other keys than Enter', () => {
+ host.innerHTML = '';
+ const input = host.querySelector('input');
+
+ expect(dispatchKeydown(input, { key: 'a' })).toBeFalse();
+ expect(dispatchKeydown(input, { key: ' ' })).toBeFalse();
+ });
+
+ it('should not prevent Enter while an IME composition is in progress', () => {
+ host.innerHTML = '';
+
+ expect(dispatchKeydown(host.querySelector('input'), { isComposing: true })).toBeFalse();
+ });
+
+ it('should resolve the target of the event through its composed path', () => {
+ const shadowHost = document.createElement('div');
+ host.appendChild(shadowHost);
+ const shadowRoot = shadowHost.attachShadow({ mode: 'open' });
+ shadowRoot.innerHTML = '';
+ const input = shadowRoot.querySelector('input');
+
+ expect(input.form).toBe(shadowRoot.querySelector('form'));
+ expect(dispatchKeydown(input)).toBeTrue();
+ });
+ });
});
diff --git a/projects/igniteui-angular/core/src/core/utils.ts b/projects/igniteui-angular/core/src/core/utils.ts
index 12cc7c76c89..d5406afd7a5 100644
--- a/projects/igniteui-angular/core/src/core/utils.ts
+++ b/projects/igniteui-angular/core/src/core/utils.ts
@@ -479,6 +479,25 @@ export const NAVIGATION_KEYS = new Set([
' '
]);
+/** Input types on which Enter has its own activation behavior instead of submitting the form. */
+const ACTIVATABLE_INPUT_TYPES = new Set(['button', 'submit', 'reset', 'image', 'file', 'color']);
+
+/**
+ * @hidden
+ * @internal
+ *
+ * Cancels the implicit submission of the surrounding form, which the browser performs as the default action
+ * of an Enter keydown in an ``.
+ * Only inputs which have a form owner and no activation behavior of their own are affected.
+ */
+export function preventImplicitSubmission(event: KeyboardEvent): void {
+ const target = event.composedPath()[0];
+ if (event.key === 'Enter' && !event.isComposing && target instanceof HTMLInputElement &&
+ target.form && !ACTIVATABLE_INPUT_TYPES.has(target.type)) {
+ event.preventDefault();
+ }
+}
+
/**
* @hidden
* @internal
diff --git a/projects/igniteui-angular/grids/core/src/column-actions/column-actions.component.html b/projects/igniteui-angular/grids/core/src/column-actions/column-actions.component.html
index 071b64a2ac8..f3c17cc979e 100644
--- a/projects/igniteui-angular/grids/core/src/column-actions/column-actions.component.html
+++ b/projects/igniteui-angular/grids/core/src/column-actions/column-actions.component.html
@@ -10,7 +10,8 @@
{{ title }}
+ autocomplete="off"
+ (keydown)="preventImplicitSubmission($event)" />
}
diff --git a/projects/igniteui-angular/grids/core/src/column-actions/column-actions.component.ts b/projects/igniteui-angular/grids/core/src/column-actions/column-actions.component.ts
index 0c474bc8585..ce8a36af154 100644
--- a/projects/igniteui-angular/grids/core/src/column-actions/column-actions.component.ts
+++ b/projects/igniteui-angular/grids/core/src/column-actions/column-actions.component.ts
@@ -7,7 +7,7 @@ import { FormsModule } from '@angular/forms';
import { IgxInputDirective, IgxInputGroupComponent } from 'igniteui-angular/input-group';
import { IgxCheckboxComponent } from 'igniteui-angular/checkbox';
import { IgxButtonDirective, IgxRippleDirective } from 'igniteui-angular/directives';
-import { ColumnType } from 'igniteui-angular/core';
+import { ColumnType, preventImplicitSubmission } from 'igniteui-angular/core';
let NEXT_ID = 0;
/**
@@ -24,6 +24,8 @@ let NEXT_ID = 0;
export class IgxColumnActionsComponent implements DoCheck {
private differs = inject(IterableDiffers);
+ protected readonly preventImplicitSubmission = preventImplicitSubmission;
+
/**
* Gets/Sets the grid to provide column actions for.
diff --git a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts
index 71eeba662cb..803c7b2f55e 100644
--- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts
+++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts
@@ -94,7 +94,8 @@ import {
IgxOverlayOutletDirective,
DEFAULT_LOCALE,
onResourceChangeHandle,
- runAfterRenderOnce
+ runAfterRenderOnce,
+ preventImplicitSubmission
} from 'igniteui-angular/core';
import { IgcTrialWatermark } from 'igniteui-trial-watermark';
import { Subject, pipe, fromEvent, animationFrameScheduler, merge, BehaviorSubject, timer } from 'rxjs';
@@ -3700,6 +3701,12 @@ export abstract class IgxGridBaseDirective implements GridType,
*/
public _setupListeners() {
const destructor = takeUntil(this.destroy$);
+ // Capture phase, since internal handlers (filtering row, editors, dialogs) stop the propagation of key events.
+ // The keypress is also handled, as a picker selecting on Enter may move the focus to its input before it.
+ merge(
+ fromEvent(this.nativeElement, 'keydown', { capture: true }),
+ fromEvent(this.nativeElement, 'keypress', { capture: true })
+ ).pipe(destructor).subscribe(preventImplicitSubmission);
fromEvent(this.nativeElement, 'focusout').pipe(filter(() => !!this.navigation.activeNode), destructor).subscribe((event) => {
const activeNode = this.navigation.activeNode;
if (!this.crudService.cell && !!activeNode &&
diff --git a/projects/igniteui-angular/grids/grid/src/grid-form-submission.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-form-submission.spec.ts
new file mode 100644
index 00000000000..14c3930b7dc
--- /dev/null
+++ b/projects/igniteui-angular/grids/grid/src/grid-form-submission.spec.ts
@@ -0,0 +1,276 @@
+import { Component, ViewChild } from '@angular/core';
+import { ComponentFixture, TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { NoopAnimationsModule } from '@angular/platform-browser/animations';
+import { IgxGridComponent } from './grid.component';
+import { FilterMode, INPUT_DEBOUNCE_TIME_DEFAULT, IgxCellTemplateDirective, IgxColumnActionsComponent, IgxColumnComponent, IgxColumnHidingDirective, IgxGridToolbarActionsComponent, IgxGridToolbarComponent, IgxGridToolbarHidingComponent } from 'igniteui-angular/grids/core';
+import { AbsoluteScrollStrategy, GlobalPositionStrategy } from 'igniteui-angular/core';
+import { IgxInputDirective } from 'igniteui-angular/input-group';
+import { IgxDatePickerComponent } from 'igniteui-angular/date-picker';
+import { GridFunctions } from '../../../test-utils/grid-functions.spec';
+import { QueryBuilderFunctions } from '../../../query-builder/src/query-builder/query-builder-functions.spec';
+
+const FILTER_UI_ROW = 'igx-grid-filtering-row';
+const UNTYPED_BUTTONS = 'button:not([type]), button[type=submit]';
+
+const DATA = [
+ { ProductID: 1, ProductName: 'Chai', InStock: true, Released: new Date(2024, 0, 10) },
+ { ProductID: 2, ProductName: 'Aniseed Syrup', InStock: false, Released: new Date(2024, 1, 11) },
+ { ProductID: 3, ProductName: 'Chef Antons Cajun Seasoning', InStock: true, Released: new Date(2024, 2, 12) }
+];
+
+/**
+ * Dispatches a keyboard event on the target and returns it.
+ * The browser performs the implicit submission as the default action of the Enter key, so a cancelled event does not submit the form.
+ */
+const pressKey = (target: Element, key = 'Enter', type = 'keydown'): KeyboardEvent => {
+ const event = new KeyboardEvent(type, { key, bubbles: true, cancelable: true, composed: true });
+ target.dispatchEvent(event);
+ return event;
+};
+
+const addAdvancedFilteringCondition = (fixture: ComponentFixture): HTMLInputElement => {
+ QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fixture, 0);
+ tick(100);
+ fixture.detectChanges();
+ QueryBuilderFunctions.selectColumnInEditModeExpression(fixture, 1); // 'ProductName'
+ QueryBuilderFunctions.selectOperatorInEditModeExpression(fixture, 2); // 'Starts With'
+ return QueryBuilderFunctions.getQueryBuilderValueInput(fixture).querySelector('input');
+};
+
+describe('IgxGrid - implicit form submission #grid', () => {
+ let fixture: ComponentFixture;
+ let grid: IgxGridComponent;
+ let form: HTMLFormElement;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ imports: [NoopAnimationsModule, GridInFormComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(fakeAsync(() => {
+ fixture = TestBed.createComponent(GridInFormComponent);
+ fixture.detectChanges();
+ tick(100);
+ fixture.detectChanges();
+ grid = fixture.componentInstance.grid;
+ form = fixture.nativeElement.querySelector('form');
+ }));
+
+ it('should not render buttons which can become the default button of the form', () => {
+ // The add row snackbar is always rendered and was the default button of the form before the fix.
+ expect(grid.nativeElement.querySelector('igx-snackbar button').getAttribute('type')).toBe('button');
+ expect(grid.nativeElement.querySelectorAll(UNTYPED_BUTTONS).length).toBe(0);
+ const defaultButton = form.querySelector('button:not([type]), button[type=submit], input[type=submit]');
+ expect(defaultButton.id).toBe('submit');
+ });
+
+ it('should prevent implicit submission on Enter in the filtering row input', fakeAsync(() => {
+ GridFunctions.clickFilterCellChipUI(fixture, 'ProductName');
+ tick(100);
+ fixture.detectChanges();
+
+ const input: HTMLInputElement = fixture.debugElement.query(By.css(FILTER_UI_ROW)).query(By.directive(IgxInputDirective)).nativeElement;
+ expect(input.form).toBe(form);
+ // Typing must keep working: only Enter is cancelled.
+ expect(pressKey(input, 'a').defaultPrevented).toBeFalse();
+
+ GridFunctions.typeValueInFilterRowInput('Chai', fixture);
+ tick(INPUT_DEBOUNCE_TIME_DEFAULT);
+ fixture.detectChanges();
+
+ expect(pressKey(input).defaultPrevented).toBeTrue();
+ tick(100);
+ fixture.detectChanges();
+
+ expect(grid.rowList.map(row => row.data.ProductName)).toEqual(['Chai']);
+ }));
+
+ it('should prevent implicit submission on Enter in a cell editor', () => {
+ const cell = grid.getCellByColumn(0, 'ProductName');
+ cell.editMode = true;
+ fixture.detectChanges();
+
+ const input: HTMLInputElement = grid.nativeElement.querySelector('.igx-grid__td--editing input');
+ expect(input.form).toBe(form);
+ expect(pressKey(input).defaultPrevented).toBeTrue();
+ });
+
+ it('should prevent implicit submission on Enter in the toolbar column hiding search input', fakeAsync(() => {
+ const hidingButton: HTMLButtonElement = fixture.nativeElement.querySelector('igx-grid-toolbar-hiding button');
+ hidingButton.click();
+ tick(100);
+ fixture.detectChanges();
+
+ const input: HTMLInputElement = grid.nativeElement.querySelector('igx-column-actions input');
+ expect(input.form).toBe(form);
+ expect(pressKey(input).defaultPrevented).toBeTrue();
+ }));
+
+ it('should prevent implicit submission on Enter in the excel style filtering custom dialog input', fakeAsync(() => {
+ grid.filterMode = FilterMode.excelStyleFilter;
+ fixture.detectChanges();
+
+ GridFunctions.clickExcelFilterIconFromCode(fixture, grid, 'ProductName');
+ GridFunctions.clickExcelFilterCascadeButton(fixture);
+ tick(100);
+ fixture.detectChanges();
+ GridFunctions.clickOperatorFromCascadeMenu(fixture, 0);
+ tick(200);
+ fixture.detectChanges();
+
+ const input = GridFunctions.getExcelFilteringInput(fixture, 0);
+ expect(input.form).toBe(form);
+ expect(pressKey(input).defaultPrevented).toBeTrue();
+ }));
+
+ it('should prevent implicit submission on Enter in the advanced filtering dialog opened with custom overlay settings', fakeAsync(() => {
+ grid.openAdvancedFilteringDialog({
+ closeOnOutsideClick: false,
+ modal: false,
+ positionStrategy: new GlobalPositionStrategy(),
+ scrollStrategy: new AbsoluteScrollStrategy()
+ });
+ tick(100);
+ fixture.detectChanges();
+
+ const input = addAdvancedFilteringCondition(fixture);
+ expect(grid.nativeElement.contains(input)).toBeFalse();
+ expect(input.form).toBe(form);
+ expect(pressKey(input).defaultPrevented).toBeTrue();
+
+ grid.closeAdvancedFilteringDialog(false);
+ tick(100);
+ }));
+
+ it('should prevent implicit submission on Enter in a filtering row date picker calendar, which moves the focus to its input', fakeAsync(() => {
+ GridFunctions.clickFilterCellChipUI(fixture, 'Released');
+ tick(100);
+ fixture.detectChanges();
+
+ const filteringRow = fixture.debugElement.query(By.css(FILTER_UI_ROW));
+ const datePicker = filteringRow.query(By.directive(IgxDatePickerComponent)).componentInstance as IgxDatePickerComponent;
+ (datePicker.getEditElement() as HTMLElement).click();
+ tick(100);
+ fixture.detectChanges();
+ expect(datePicker.collapsed).toBeFalse();
+ expect(document.activeElement.closest('igx-calendar')).not.toBeNull();
+
+ // Selecting a date with Enter closes the picker and focuses its input during the keydown, so the browser
+ // performs the implicit submission on the following keypress, which targets that input.
+ pressKey(document.activeElement);
+ tick(100);
+ fixture.detectChanges();
+
+ const pickerInput = document.activeElement as HTMLInputElement;
+ expect(datePicker.collapsed).toBeTrue();
+ expect(pickerInput.form).toBe(form);
+ expect(pressKey(pickerInput, 'Enter', 'keypress').defaultPrevented).toBeTrue();
+ }));
+
+ it('should not prevent the native Enter behavior of other elements inside the grid', () => {
+ const fileInput = grid.nativeElement.querySelector('input[type=file]') as HTMLInputElement;
+ expect(fileInput.form).toBe(form);
+
+ expect(pressKey(grid.nativeElement.querySelector('summary')).defaultPrevented).toBeFalse();
+ expect(pressKey(fileInput).defaultPrevented).toBeFalse();
+ expect(pressKey(grid.nativeElement.querySelector('input[type=color]')).defaultPrevented).toBeFalse();
+ });
+
+ it('should not affect implicit submission from inputs outside the grid', () => {
+ const outerInput: HTMLInputElement = fixture.nativeElement.querySelector('#outerInput');
+ expect(pressKey(outerInput).defaultPrevented).toBeFalse();
+ expect(pressKey(outerInput, 'Enter', 'keypress').defaultPrevented).toBeFalse();
+ });
+});
+
+describe('IgxGrid - implicit form submission from grid components outside of the grid #grid', () => {
+ let fixture: ComponentFixture;
+ let form: HTMLFormElement;
+
+ beforeEach(waitForAsync(() => {
+ TestBed.configureTestingModule({
+ imports: [NoopAnimationsModule, GridComponentsInFormComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(fakeAsync(() => {
+ fixture = TestBed.createComponent(GridComponentsInFormComponent);
+ fixture.detectChanges();
+ tick(100);
+ fixture.detectChanges();
+ form = fixture.nativeElement.querySelector('form');
+ }));
+
+ it('should prevent implicit submission on Enter in the standalone column actions filter input', () => {
+ const input: HTMLInputElement = fixture.nativeElement.querySelector('#standaloneActions input');
+ expect(fixture.componentInstance.grid.nativeElement.contains(input)).toBeFalse();
+ expect(input.form).toBe(form);
+ expect(pressKey(input).defaultPrevented).toBeTrue();
+ });
+});
+
+@Component({
+ template: `
+ `,
+ imports: [
+ IgxGridComponent,
+ IgxColumnComponent,
+ IgxCellTemplateDirective,
+ IgxGridToolbarComponent,
+ IgxGridToolbarActionsComponent,
+ IgxGridToolbarHidingComponent
+ ]
+})
+class GridInFormComponent {
+ @ViewChild('grid', { static: true })
+ public grid: IgxGridComponent;
+
+ public data = DATA;
+}
+
+@Component({
+ template: `
+ `,
+ imports: [
+ IgxGridComponent,
+ IgxColumnComponent,
+ IgxColumnActionsComponent,
+ IgxColumnHidingDirective
+ ]
+})
+class GridComponentsInFormComponent {
+ @ViewChild('grid', { static: true })
+ public grid: IgxGridComponent;
+
+ public data = DATA;
+}
diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.component.html b/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.component.html
index 5a41d48b3bb..2272a7af02f 100644
--- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.component.html
+++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.component.html
@@ -7,6 +7,7 @@
tabindex="0"
placeholder="Search"
autocomplete="off"
+ (keydown)="preventImplicitSubmission($event)"
/>
diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.component.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.component.ts
index a8a6307ea64..07172ff9511 100644
--- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.component.ts
+++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.component.ts
@@ -12,7 +12,7 @@ import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansio
import { IDragBaseEventArgs, IDragGhostBaseEventArgs, IDragMoveEventArgs, IDropBaseEventArgs, IDropDroppedEventArgs, IgxDragDirective, IgxDragHandleDirective, IgxDropDirective } from 'igniteui-angular/directives';
import { IgxChipComponent } from 'igniteui-angular/chips';
import { IgxDropDownComponent, IgxDropDownItemComponent, IgxDropDownItemNavigationDirective, ISelectionEventArgs } from 'igniteui-angular/drop-down';
-import { AbsoluteScrollStrategy, AutoPositionStrategy, ColumnType, OverlaySettings, PositionSettings, ɵSize, SortingDirection, VerticalAlignment } from 'igniteui-angular/core';
+import { AbsoluteScrollStrategy, AutoPositionStrategy, ColumnType, OverlaySettings, PositionSettings, preventImplicitSubmission, ɵSize, SortingDirection, VerticalAlignment } from 'igniteui-angular/core';
import { IPivotAggregator, IPivotDimension, IPivotValue, PivotDimensionType, PivotGridType, PivotUtil } from 'igniteui-angular/grids/core';
interface IDataSelectorPanel {
@@ -57,6 +57,8 @@ export class IgxPivotDataSelectorComponent {
private renderer = inject(Renderer2);
private cdr = inject(ChangeDetectorRef);
+ protected readonly preventImplicitSubmission = preventImplicitSubmission;
+
/**
* Gets/sets whether the columns panel is expanded
diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.spec.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.spec.ts
index e5d1ac8f61b..b7a64a0f7d0 100644
--- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.spec.ts
+++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.spec.ts
@@ -34,6 +34,27 @@ describe("Pivot data selector", () => {
fixture.detectChanges();
expect(fixture.componentInstance).toBeDefined();
});
+
+ it("should prevent implicit form submission on Enter in its search input", () => {
+ const fixture = TestBed.createComponent(IgxPivotDataSelectorComponent);
+ fixture.detectChanges();
+
+ const input = fixture.debugElement.query(By.directive(IgxInputDirective)).nativeElement as HTMLInputElement;
+ const pressEnter = () => {
+ const event = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true });
+ input.dispatchEvent(event);
+ return event.defaultPrevented;
+ };
+
+ expect(pressEnter()).toBeFalse();
+
+ const form = document.createElement('form');
+ fixture.nativeElement.parentElement.appendChild(form);
+ form.appendChild(fixture.nativeElement);
+ expect(input.form).toBe(form);
+ expect(pressEnter()).toBeTrue();
+ form.remove();
+ });
});
describe("Pivot data selector integration", () => {
diff --git a/projects/igniteui-angular/query-builder/src/query-builder/query-builder-tree.component.html b/projects/igniteui-angular/query-builder/src/query-builder/query-builder-tree.component.html
index 12f6069238c..99599118e00 100644
--- a/projects/igniteui-angular/query-builder/src/query-builder/query-builder-tree.component.html
+++ b/projects/igniteui-angular/query-builder/src/query-builder/query-builder-tree.component.html
@@ -257,7 +257,7 @@
@if (expressionItem.focused || expressionItem.hovered) {