Skip to content

Commit 9837df5

Browse files
committed
Merge branch 'master' of https://github.com/IgniteUI/igniteui-angular into copilot/support-multiple-entry-points
2 parents b73740a + 4911a76 commit 9837df5

File tree

6 files changed

+106
-62
lines changed

6 files changed

+106
-62
lines changed

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import {
22
Directive, OnInit, OnDestroy, Output, ElementRef, Optional, ViewContainerRef, HostListener,
3-
Input, EventEmitter, booleanAttribute, TemplateRef, ComponentRef, Renderer2, OnChanges, SimpleChanges,
3+
Input, EventEmitter, booleanAttribute, TemplateRef, ComponentRef, Renderer2,
44
EnvironmentInjector,
55
createComponent,
6+
AfterViewInit,
67
} from '@angular/core';
78
import { Subject } from 'rxjs';
89
import { takeUntil } from 'rxjs/operators';
@@ -45,7 +46,7 @@ export interface ITooltipHideEventArgs extends IBaseEventArgs {
4546
selector: '[igxTooltipTarget]',
4647
standalone: true
4748
})
48-
export class IgxTooltipTargetDirective extends IgxToggleActionDirective implements OnChanges, OnInit, OnDestroy {
49+
export class IgxTooltipTargetDirective extends IgxToggleActionDirective implements OnInit, AfterViewInit, OnDestroy {
4950
/**
5051
* Gets/sets the amount of milliseconds that should pass before showing the tooltip.
5152
*
@@ -101,7 +102,7 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
101102
*/
102103
@Input()
103104
public set hasArrow(value: boolean) {
104-
if (this.target) {
105+
if (this.target && this.target.arrow) {
105106
this.target.arrow.style.display = value ? '' : 'none';
106107
}
107108
this._hasArrow = value;
@@ -397,16 +398,6 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
397398
}
398399
}
399400

400-
401-
/**
402-
* @hidden
403-
*/
404-
public ngOnChanges(changes: SimpleChanges): void {
405-
if (changes['hasArrow']) {
406-
this.target.arrow.style.display = changes['hasArrow'].currentValue ? '' : 'none';
407-
}
408-
}
409-
410401
/**
411402
* @hidden
412403
*/
@@ -433,6 +424,15 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
433424
this.nativeElement.addEventListener('touchstart', this.onTouchStart = this.onTouchStart.bind(this), { passive: true });
434425
}
435426

427+
/**
428+
* @hidden
429+
*/
430+
public ngAfterViewInit(): void {
431+
if (this.target && this.target.arrow) {
432+
this.target.arrow.style.display = this.hasArrow ? '' : 'none';
433+
}
434+
}
435+
436436
/**
437437
* @hidden
438438
*/
@@ -559,8 +559,6 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
559559

560560
/**
561561
* Used when a single tooltip is used for multiple targets.
562-
* If the tooltip is shown for one target and the user interacts with another target,
563-
* the tooltip is instantly hidden for the first target.
564562
*/
565563
private _checkTooltipForMultipleTargets(): void {
566564
if (!this.target.tooltipTarget) {
@@ -573,8 +571,10 @@ export class IgxTooltipTargetDirective extends IgxToggleActionDirective implemen
573571
this.target.tooltipTarget._removeCloseButtonFromTooltip();
574572
}
575573

574+
// If the tooltip is shown for one target and the user interacts with another target,
575+
// the tooltip is instantly hidden for the first target.
576576
clearTimeout(this.target.timeoutId);
577-
this.target.stopAnimations(true);
577+
this.target.forceClose(this._mergedOverlaySettings);
578578

579579
this.target.tooltipTarget = this;
580580
this._isForceClosed = true;

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,31 @@ describe('IgxTooltip', () => {
558558
flush();
559559
}));
560560

561+
it('Should position relative to its target when having no close animation - #16288', fakeAsync(() => {
562+
targetOne.positionSettings = targetTwo.positionSettings = {
563+
openAnimation: undefined,
564+
closeAnimation: undefined
565+
};
566+
fix.detectChanges();
567+
568+
hoverElement(buttonOne);
569+
tick(targetOne.showDelay);
570+
571+
verifyTooltipVisibility(tooltipNativeElement, targetOne, true);
572+
verifyTooltipPosition(tooltipNativeElement, buttonOne, true);
573+
574+
unhoverElement(buttonOne);
575+
576+
hoverElement(buttonTwo);
577+
tick(targetTwo.showDelay);
578+
579+
// Tooltip is visible and positioned relative to buttonTwo
580+
verifyTooltipVisibility(tooltipNativeElement, targetTwo, true);
581+
verifyTooltipPosition(tooltipNativeElement, buttonTwo);
582+
// Tooltip is NOT visible and positioned relative to buttonOne
583+
verifyTooltipPosition(tooltipNativeElement, buttonOne, false);
584+
}));
585+
561586
it('Hovering first target briefly and then hovering second target leads to tooltip showing for second target', fakeAsync(() => {
562587
targetOne.showDelay = 600;
563588
fix.detectChanges();

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

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import {
22
Directive, ElementRef, Input, ChangeDetectorRef, Optional, HostBinding, Inject,
33
OnDestroy, inject, DOCUMENT, HostListener,
4+
Renderer2,
5+
AfterViewInit,
46
} from '@angular/core';
5-
import { IgxOverlayService } from 'igniteui-angular/core';
7+
import { IgxOverlayService, OverlaySettings, PlatformUtil } from 'igniteui-angular/core';
68
import { IgxNavigationService } from 'igniteui-angular/core';
79
import { IgxToggleDirective } from '../toggle/toggle.directive';
810
import { IgxTooltipTargetDirective } from './tooltip-target.directive';
@@ -28,7 +30,7 @@ let NEXT_ID = 0;
2830
selector: '[igxTooltip]',
2931
standalone: true
3032
})
31-
export class IgxTooltipDirective extends IgxToggleDirective implements OnDestroy {
33+
export class IgxTooltipDirective extends IgxToggleDirective implements AfterViewInit, OnDestroy {
3234
/**
3335
* @hidden
3436
*/
@@ -116,6 +118,8 @@ export class IgxTooltipDirective extends IgxToggleDirective implements OnDestroy
116118
private _role: 'tooltip' | 'status' = 'tooltip';
117119
private _destroy$ = new Subject<boolean>();
118120
private _document = inject(DOCUMENT);
121+
private _renderer = inject(Renderer2);
122+
private _platformUtil = inject(PlatformUtil);
119123

120124
/** @hidden */
121125
constructor(
@@ -133,8 +137,13 @@ export class IgxTooltipDirective extends IgxToggleDirective implements OnDestroy
133137
this.closed.pipe(takeUntil(this._destroy$)).subscribe(() => {
134138
this._document.removeEventListener('touchstart', this.onDocumentTouchStart);
135139
});
140+
}
136141

137-
this._createArrow();
142+
/** @hidden */
143+
public ngAfterViewInit(): void {
144+
if (this._platformUtil.isBrowser) {
145+
this._createArrow();
146+
}
138147
}
139148

140149
/** @hidden */
@@ -144,7 +153,10 @@ export class IgxTooltipDirective extends IgxToggleDirective implements OnDestroy
144153
this._document.removeEventListener('touchstart', this.onDocumentTouchStart);
145154
this._destroy$.next(true);
146155
this._destroy$.complete();
147-
this._removeArrow();
156+
157+
if (this.arrow) {
158+
this._removeArrow();
159+
}
148160
}
149161

150162
/**
@@ -165,37 +177,51 @@ export class IgxTooltipDirective extends IgxToggleDirective implements OnDestroy
165177

166178
/**
167179
* If there is an animation in progress, this method will reset it to its initial state.
168-
* Optional `force` parameter that ends the animation.
180+
* Allows hovering over the tooltip while an open/close animation is running.
181+
* Stops the animation and immediately shows the tooltip.
169182
*
170183
* @hidden
171-
* @param force if set to `true`, the animation will be ended.
172184
*/
173-
public stopAnimations(force: boolean = false): void {
185+
public stopAnimations(): void {
174186
const info = this.overlayService.getOverlayById(this._overlayId);
175187

176188
if (!info) return;
177189

178190
if (info.openAnimationPlayer) {
179191
info.openAnimationPlayer.reset();
180-
if (force) {
181-
info.openAnimationPlayer.finish();
182-
info.openAnimationPlayer = null;
183-
}
184192
}
185193
if (info.closeAnimationPlayer) {
186194
info.closeAnimationPlayer.reset();
187-
if (force) {
188-
info.closeAnimationPlayer.finish();
189-
info.closeAnimationPlayer = null;
190-
}
195+
}
196+
}
197+
198+
/**
199+
* If there is a close animation in progress, this method will end it.
200+
* If there is no close animation in progress, this method will close the tooltip with no animation.
201+
*
202+
* @param overlaySettings settings to use for closing the tooltip
203+
* @hidden
204+
*/
205+
public forceClose(overlaySettings: OverlaySettings) {
206+
const info = this.overlayService.getOverlayById(this._overlayId);
207+
208+
if (info && info.closeAnimationPlayer) {
209+
info.closeAnimationPlayer.finish();
210+
info.closeAnimationPlayer.reset();
211+
info.closeAnimationPlayer = null;
212+
} else if (!this.collapsed) {
213+
const animation = overlaySettings.positionStrategy.settings.closeAnimation;
214+
overlaySettings.positionStrategy.settings.closeAnimation = null;
215+
this.close();
216+
overlaySettings.positionStrategy.settings.closeAnimation = animation;
191217
}
192218
}
193219

194220
private _createArrow(): void {
195-
this._arrowEl = document.createElement('span');
196-
this._arrowEl.style.position = 'absolute';
197-
this._arrowEl.setAttribute('data-arrow', 'true');
198-
this.element.appendChild(this._arrowEl);
221+
this._arrowEl = this._renderer.createElement('span');
222+
this._renderer.setStyle(this._arrowEl, 'position', 'absolute');
223+
this._renderer.setAttribute(this._arrowEl, 'data-arrow', 'true');
224+
this._renderer.appendChild(this.element, this._arrowEl);
199225
}
200226

201227
private _removeArrow(): void {

projects/igniteui-angular/grids/src/grids/grid/grid-validation.spec.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ describe('IgxGrid - Validation #grid', () => {
167167
cell = grid.gridAPI.get_cell_by_visible_index(1, 1);
168168
//min length should be 4
169169
GridFunctions.verifyCellValid(cell, false);
170-
const erorrMessage = cell.errorTooltip.first.elementRef.nativeElement.children[1].textContent;
171-
expect(erorrMessage).toEqual(' Entry should be at least 4 character(s) long ');
170+
const errorMessage = cell.errorTooltip.first.elementRef.nativeElement.children[0].textContent;
171+
expect(errorMessage).toEqual(' Entry should be at least 4 character(s) long ');
172172
});
173173

174174
it('should mark invalid cell with igx-grid__td--invalid class and show the related error cell template when the field contains "."', () => {
@@ -186,8 +186,8 @@ describe('IgxGrid - Validation #grid', () => {
186186
cell = grid.gridAPI.get_cell_by_visible_index(1, 4);
187187
//min length should be 4
188188
GridFunctions.verifyCellValid(cell, false);
189-
const erorrMessage = cell.errorTooltip.first.elementRef.nativeElement.children[1].textContent;
190-
expect(erorrMessage).toEqual(' Entry should be at least 4 character(s) long ');
189+
const errorMessage = cell.errorTooltip.first.elementRef.nativeElement.children[0].textContent;
190+
expect(errorMessage).toEqual(' Entry should be at least 4 character(s) long ');
191191
});
192192

193193
it('should show the error message on error icon hover and when the invalid cell becomes active.', fakeAsync(() => {
@@ -204,8 +204,8 @@ describe('IgxGrid - Validation #grid', () => {
204204
//min length should be 4
205205
GridFunctions.verifyCellValid(cell, false);
206206
GridSelectionFunctions.verifyCellActive(cell, true);
207-
const erorrMessage = cell.errorTooltip.first.elementRef.nativeElement.children[1].textContent;
208-
expect(erorrMessage).toEqual(' Entry should be at least 4 character(s) long ');
207+
const errorMessage = cell.errorTooltip.first.elementRef.nativeElement.children[0].textContent;
208+
expect(errorMessage).toEqual(' Entry should be at least 4 character(s) long ');
209209

210210
const overlayService = TestBed.inject(IgxOverlayService);
211211
const info = overlayService.getOverlayById(cell.errorTooltip.first.overlayId);
@@ -390,8 +390,8 @@ describe('IgxGrid - Validation #grid', () => {
390390
cell = grid.gridAPI.get_cell_by_visible_index(1, 1);
391391
//bob cannot be the name
392392
GridFunctions.verifyCellValid(cell, false);
393-
const erorrMessage = cell.errorTooltip.first.elementRef.nativeElement.children[1].textContent;
394-
expect(erorrMessage).toEqual(' This name is forbidden. ');
393+
const errorMessage = cell.errorTooltip.first.elementRef.nativeElement.children[0].textContent;
394+
expect(errorMessage).toEqual(' This name is forbidden. ');
395395

396396
cell.editMode = true;
397397
cell.update('test');
@@ -425,8 +425,8 @@ describe('IgxGrid - Validation #grid', () => {
425425
fixture.detectChanges();
426426

427427
GridFunctions.verifyCellValid(cell, false);
428-
const erorrMessage = cell.errorTooltip.first.elementRef.nativeElement.children[1].textContent;
429-
expect(erorrMessage).toEqual(' Entry should be at least 4 character(s) long ');
428+
const errorMessage = cell.errorTooltip.first.elementRef.nativeElement.children[0].textContent;
429+
expect(errorMessage).toEqual(' Entry should be at least 4 character(s) long ');
430430
});
431431

432432
it('should trigger validation on change when using custom editor bound via editValue.', () => {
@@ -444,8 +444,8 @@ describe('IgxGrid - Validation #grid', () => {
444444
fixture.detectChanges();
445445

446446
GridFunctions.verifyCellValid(cell, false);
447-
const erorrMessage = cell.errorTooltip.first.elementRef.nativeElement.children[1].textContent;
448-
expect(erorrMessage).toEqual(' Entry should be at least 4 character(s) long ');
447+
const errorMessage = cell.errorTooltip.first.elementRef.nativeElement.children[0].textContent;
448+
expect(errorMessage).toEqual(' Entry should be at least 4 character(s) long ');
449449
});
450450

451451
it('should trigger validation on blur when using custom editor bound via editValue.', () => {
@@ -472,8 +472,8 @@ describe('IgxGrid - Validation #grid', () => {
472472
grid.crudService.endEdit(true);
473473
fixture.detectChanges();
474474
GridFunctions.verifyCellValid(cell, false);
475-
const erorrMessage = cell.errorTooltip.first.elementRef.nativeElement.children[1].textContent;
476-
expect(erorrMessage).toEqual(' Entry should be at least 4 character(s) long ');
475+
const errorMessage = cell.errorTooltip.first.elementRef.nativeElement.children[0].textContent;
476+
expect(errorMessage).toEqual(' Entry should be at least 4 character(s) long ');
477477
});
478478
});
479479

projects/igniteui-angular/splitter/src/splitter/splitter.component.spec.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -490,27 +490,22 @@ describe('IgxSplitter resizing with minSize and browser window is shrinked', ()
490490
const minSize = parseInt(pane1.minSize);
491491
spyOn(splitter, 'onMoveEnd').and.callThrough();
492492

493-
pane1.size = (splitter.getTotalSize() - parseInt(pane2.size)) + 'px';
494-
fixture.detectChanges();
495-
496493
splitterBarComponent.moveStart.emit(pane1);
497494
fixture.detectChanges();
498495
splitterBarComponent.movingEnd.emit(splitter.getTotalSize() -minSize);
499496
fixture.detectChanges();
500497

501498
splitter.elementRef.nativeElement.style.width = '500px';
502-
pane2.size = (splitter.getTotalSize() - minSize) + 'px';
503499
fixture.detectChanges();
504500

505501
splitterBarComponent.moveStart.emit(pane1);
506502
fixture.detectChanges();
507-
splitterBarComponent.movingEnd.emit(-400);
503+
splitterBarComponent.movingEnd.emit(-200);
508504
fixture.detectChanges();
509505

510-
const isFullSize = pane1.size === '100%' || pane1.size === (splitter.getTotalSize() + 'px');
511-
512506
expect(splitter.onMoveEnd).toHaveBeenCalled();
513-
expect(isFullSize).toBeTruthy();
507+
expect(pane1.size).toEqual('80%');
508+
expect(pane2.size).toEqual('100px');
514509
});
515510
});
516511

projects/igniteui-angular/splitter/src/splitter/splitter.component.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,9 @@ export class IgxSplitterComponent implements AfterContentInit {
244244
let [ paneSize, siblingSize ] = this.calcNewSizes(delta);
245245

246246
if (paneSize + siblingSize > this.getTotalSize() && delta < 0) {
247-
paneSize = this.getTotalSize();
248-
siblingSize = 0;
249-
} else if(paneSize + siblingSize > this.getTotalSize() && delta > 0) {
250-
paneSize = 0;
251-
siblingSize = this.getTotalSize();
247+
siblingSize = this.getTotalSize() - paneSize;
248+
} else if (paneSize + siblingSize > this.getTotalSize() && delta > 0) {
249+
paneSize = this.getTotalSize() - siblingSize;
252250
}
253251

254252
if (this.pane.isPercentageSize) {

0 commit comments

Comments
 (0)