Skip to content

Commit 2b18ce9

Browse files
jackofdiamond5ChronosSFLipata
authored
fix(igxTextSelection): Wrap nativeElement.select in a raf call - 15.1.x (#12646)
* refactor(igxTextSelection): wrap nativeElement.select in a raf call * test(IgxTextSelection): wrap expects in a raf call * chore(IgxTextSelection): add comment on the raf call * test(IgxTextSelection): should apply selection properly * refactor(IgxTextSelection): change names of test component/directive * test(IgxTextSelection): use tick to delay expects --------- Co-authored-by: Stamen Stoychev <[email protected]> Co-authored-by: Nikolay Alipiev <[email protected]>
1 parent 418254c commit 2b18ce9

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

projects/igniteui-angular/src/lib/directives/text-selection/text-selection.directive.spec.ts

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, DebugElement, ViewChild } from '@angular/core';
1+
import { Component, DebugElement, Directive, ElementRef, HostListener, ViewChild } from '@angular/core';
22
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44
import { IgxTextSelectionModule } from './text-selection.directive';
@@ -12,24 +12,26 @@ describe('IgxSelection', () => {
1212
declarations: [
1313
TriggerTextSelectionComponent,
1414
TriggerTextSelectionOnClickComponent,
15+
TextSelectionWithMultipleFocusHandlersComponent,
16+
IgxTestFocusDirective
1517
],
1618
imports: [IgxTextSelectionModule]
1719
});
1820
}));
1921

2022

21-
it('Should select the text which is into the input', () => {
23+
it('Should select the text which is into the input', fakeAsync(() => {
2224
const fix = TestBed.createComponent(TriggerTextSelectionComponent);
2325
fix.detectChanges();
2426

2527
const input = fix.debugElement.query(By.css('input')).nativeElement;
2628
input.focus();
27-
29+
tick(16);
2830
expect(input.selectionEnd).toEqual(input.value.length);
2931
expect(input.value.substring(input.selectionStart, input.selectionEnd)).toEqual(input.value);
30-
});
32+
}));
3133

32-
it('Should select the text when the input is clicked', ()=> {
34+
it('Should select the text when the input is clicked', fakeAsync(()=> {
3335
const fix = TestBed.createComponent(TriggerTextSelectionOnClickComponent);
3436
fix.detectChanges();
3537

@@ -39,11 +41,11 @@ describe('IgxSelection', () => {
3941

4042
inputElem.click(); // might need to change to .focus
4143
fix.detectChanges();
42-
44+
tick(16);
4345
expect(inputNativeElem.selectionEnd).toEqual(inputNativeElem.value.length);
4446
expect(inputNativeElem.value.substring(inputNativeElem.selectionStart, inputNativeElem.selectionEnd))
4547
.toEqual(inputNativeElem.value);
46-
});
48+
}));
4749

4850
it('Should check if the value is selected if based on input type', fakeAsync(() => {
4951
const fix = TestBed.createComponent(TriggerTextSelectionOnClickComponent);
@@ -81,6 +83,7 @@ describe('IgxSelection', () => {
8183

8284
inputElem.click();
8385
fix.detectChanges();
86+
tick(16);
8487

8588
if(type !== 'number'){
8689
expect(inputNativeElem.selectionEnd).toEqual(inputNativeElem.value.length);
@@ -104,6 +107,7 @@ describe('IgxSelection', () => {
104107

105108
inputElem.focus();
106109
fix.detectChanges();
110+
tick(16);
107111
expect(inputNativeElem.selectionStart).toEqual(inputNativeElem.selectionEnd);
108112
});
109113
}));
@@ -126,6 +130,17 @@ describe('IgxSelection', () => {
126130
fix.detectChanges();
127131
expect(inputNativeElem.selectionStart).toEqual(inputNativeElem.selectionEnd);
128132
});
133+
134+
it('should apply selection properly if present on an element with multiple focus handlers', fakeAsync(() => {
135+
const fix = TestBed.createComponent(TextSelectionWithMultipleFocusHandlersComponent);
136+
fix.detectChanges();
137+
138+
const input = fix.debugElement.query(By.css('input')).nativeElement;
139+
input.focus();
140+
tick(16);
141+
expect(input.selectionEnd).toEqual(input.value.length);
142+
expect(input.value.substring(input.selectionStart, input.selectionEnd)).toEqual(input.value);
143+
}));
129144
});
130145

131146
@Component({
@@ -158,6 +173,23 @@ class TriggerTextSelectionOnClickComponent {
158173
}
159174
}
160175

161-
interface Types {
162-
[key: string]: any;
176+
@Component({
177+
template: `<input #input type="text" igxTestFocusDirective [igxTextSelection]="true" [value]="inputValue" />`
178+
})
179+
class TextSelectionWithMultipleFocusHandlersComponent {
180+
public inputValue: any = "12-34-56";
163181
}
182+
183+
@Directive({selector: '[igxTestFocusDirective]'})
184+
class IgxTestFocusDirective {
185+
constructor(private element: ElementRef) { }
186+
187+
@HostListener('focus')
188+
public onFocus() {
189+
this.element.nativeElement.value = `$${this.element.nativeElement.value}`;
190+
}
191+
}
192+
193+
interface Types {
194+
[key: string]: any;
195+
}

projects/igniteui-angular/src/lib/directives/text-selection/text-selection.directive.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ export class IgxTextSelectionDirective {
108108

109109
public trigger() {
110110
if (this.selected && this.nativeElement.value.length) {
111-
this.nativeElement.select();
111+
// delay the select call to avoid race conditions in case the directive is applied
112+
// to an element with its own focus handler
113+
requestAnimationFrame(() => this.nativeElement.select());
112114
}
113115
}
114116
}

0 commit comments

Comments
 (0)