Skip to content

Commit 8ebabbb

Browse files
mddragnevviktorkombovChronosSF
authored
fix(tooltip): mark tooltip as dirty when changing its role (#17382)
* test(tooltip): add zoneless sticky tooltip test * fix(tooltip): mark tooltip as dirty when changing its role * chore: mark toggle cdr reference as protected * test(tooltip): add test for close button removal when sticky is false --------- Co-authored-by: Viktor Kombov <75325639+viktorkombov@users.noreply.github.com> Co-authored-by: Stamen Stoychev <chronos.stz@gmail.com>
1 parent b9681be commit 8ebabbb

3 files changed

Lines changed: 65 additions & 4 deletions

File tree

projects/igniteui-angular/directives/src/directives/toggle/toggle.directive.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export interface ToggleViewCancelableEventArgs extends ToggleViewEventArgs, Canc
4242
})
4343
export class IgxToggleDirective implements IToggleView, OnInit, OnDestroy {
4444
private elementRef = inject(ElementRef);
45-
private cdr = inject(ChangeDetectorRef);
45+
protected cdr = inject(ChangeDetectorRef);
4646
protected overlayService = inject<IgxOverlayService>(IgxOverlayService);
4747
private navigationService = inject(IgxNavigationService, { optional: true });
4848
private platform = inject(PlatformUtil, { optional: true });

projects/igniteui-angular/directives/src/directives/tooltip/tooltip-target.directive.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,9 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
689689
this._renderer.appendChild(this.target.element, this._closeButtonRef.location.nativeElement);
690690
this._closeButtonRef.changeDetectorRef.detectChanges();
691691
this.target.role = "status"
692+
// Mark the tooltip directive as Dirty to ensure that
693+
// the CD refreshes the bindings
694+
this.target.cdr?.markForCheck();
692695
}
693696
}
694697

@@ -700,6 +703,9 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
700703
this._renderer.removeChild(this.target.element, this._closeButtonRef.location.nativeElement);
701704
this._closeButtonRef.changeDetectorRef.detectChanges();
702705
this.target.role = "tooltip"
706+
// Mark the tooltip directive as Dirty to ensure that
707+
// the CD refreshes the bindings
708+
this.target.cdr?.markForCheck();
703709
}
704710
}
705711

projects/igniteui-angular/directives/src/directives/tooltip/tooltip.directive.spec.ts

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { DebugElement } from '@angular/core';
1+
import { DebugElement, ErrorHandler, provideZonelessChangeDetection } from '@angular/core';
22
import { fakeAsync, TestBed, tick, flush, waitForAsync, ComponentFixture } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
55
import { IgxTooltipSingleTargetComponent, IgxTooltipMultipleTargetsComponent, IgxTooltipPlainStringComponent, IgxTooltipWithToggleActionComponent, IgxTooltipWithCloseButtonComponent, IgxTooltipWithNestedContentComponent, IgxTooltipNestedTooltipsComponent } from '../../../../test-utils/tooltip-components.spec';
6-
import { UIInteractions } from '../../../../test-utils/ui-interactions.spec';
6+
import { UIInteractions, wait } from '../../../../test-utils/ui-interactions.spec';
77
import { HorizontalAlignment, VerticalAlignment, AutoPositionStrategy } from '../../../../core/src/services/public_api';
88
import { IgxTooltipDirective } from './tooltip.directive';
99
import { IgxTooltipTargetDirective } from './tooltip-target.directive';
@@ -1101,6 +1101,61 @@ describe('IgxTooltip', () => {
11011101
expect(closeBtn).toBeTruthy();
11021102
expect(tooltipNativeElement.getAttribute('role')).toBe('status');
11031103
}));
1104+
1105+
describe('Zoneless', () => {
1106+
beforeEach(async () => {
1107+
TestBed.resetTestingModule();
1108+
await TestBed.configureTestingModule({
1109+
imports: [
1110+
NoopAnimationsModule,
1111+
IgxTooltipWithCloseButtonComponent
1112+
],
1113+
providers: [provideZonelessChangeDetection()]
1114+
}).compileComponents();
1115+
});
1116+
1117+
beforeEach(() => {
1118+
fix = TestBed.createComponent(IgxTooltipWithCloseButtonComponent);
1119+
fix.detectChanges();
1120+
tooltipNativeElement = fix.debugElement.query(By.directive(IgxTooltipDirective)).nativeElement;
1121+
tooltipTarget = fix.componentInstance.tooltipTarget as IgxTooltipTargetDirective;
1122+
button = fix.debugElement.query(By.directive(IgxTooltipTargetDirective));
1123+
});
1124+
1125+
it('should not throw ExpressionChangedAfterItHasBeenChecked when showing sticky tooltip with close button', async () => {
1126+
const errorHandler = TestBed.inject(ErrorHandler);
1127+
const handleErrorSpy = spyOn(errorHandler, 'handleError');
1128+
1129+
hoverElement(button);
1130+
await wait(SHOW_DELAY + 50);
1131+
fix.detectChanges();
1132+
1133+
expect(handleErrorSpy).not.toHaveBeenCalled();
1134+
verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, true);
1135+
expect(tooltipNativeElement.getAttribute('role')).toBe('status');
1136+
});
1137+
1138+
it('should correctly remove the close button and update the role when sticky is set to false', async () => {
1139+
tooltipTarget.sticky = true;
1140+
fix.detectChanges();
1141+
hoverElement(button);
1142+
await wait(SHOW_DELAY + 50);
1143+
fix.detectChanges();
1144+
1145+
const closeBtn = tooltipNativeElement.querySelector('igx-tooltip-close-button');
1146+
expect(closeBtn).not.toBeNull();
1147+
expect(fix.componentInstance.tooltip.role).toBe('status');
1148+
1149+
tooltipTarget.sticky = false;
1150+
fix.detectChanges();
1151+
hoverElement(button);
1152+
await wait(SHOW_DELAY + 50);
1153+
fix.detectChanges();
1154+
1155+
expect(fix.componentInstance.tooltip.role).toBe('tooltip');
1156+
expect(tooltipNativeElement.querySelector('igx-tooltip-close-button')).toBeNull();
1157+
});
1158+
});
11041159
});
11051160

11061161
describe('IgxTooltip placement and offset', () => {
@@ -1188,7 +1243,7 @@ const alignmentTolerance = 2;
11881243
export const verifyTooltipPosition = (
11891244
tooltipNativeElement: HTMLElement,
11901245
actualTarget: { nativeElement: HTMLElement },
1191-
shouldAlign:boolean = true,
1246+
shouldAlign: boolean = true,
11921247
placement: Placement = Placement.Bottom,
11931248
offset: number = 6
11941249
) => {

0 commit comments

Comments
 (0)