Skip to content

Commit 75c665a

Browse files
crisbetotinayuangao
authored andcommitted
fix(tooltip): unable to type in input with tooltip on iOS (#8534)
Fixes an issue, caused by HammerJS adding `user-select: none` to the trigger element, that prevents users from being able to type inside inputs on iOS, if they have a tooltip. Fixes #8331.
1 parent d6fec35 commit 75c665a

File tree

2 files changed

+49
-2
lines changed

2 files changed

+49
-2
lines changed

src/lib/tooltip/tooltip.spec.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ describe('MatTooltip', () => {
4343
BasicTooltipDemo,
4444
ScrollableTooltipDemo,
4545
OnPushTooltipDemo,
46-
DynamicTooltipsDemo
46+
DynamicTooltipsDemo,
47+
TooltipOnTextFields
4748
],
4849
providers: [
4950
{provide: Platform, useValue: {IOS: false, isBrowser: true}},
@@ -679,6 +680,25 @@ describe('MatTooltip', () => {
679680
}));
680681
});
681682

683+
describe('special cases', () => {
684+
it('should clear the `user-select` when a tooltip is set on a text field in iOS', () => {
685+
TestBed.overrideProvider(Platform, {
686+
useValue: {IOS: true, isBrowser: true}
687+
});
688+
689+
const fixture = TestBed.createComponent(TooltipOnTextFields);
690+
const instance = fixture.componentInstance;
691+
692+
fixture.detectChanges();
693+
694+
expect(instance.input.nativeElement.style.userSelect).toBeFalsy();
695+
expect(instance.input.nativeElement.style.webkitUserSelect).toBeFalsy();
696+
697+
expect(instance.textarea.nativeElement.style.userSelect).toBeFalsy();
698+
expect(instance.textarea.nativeElement.style.webkitUserSelect).toBeFalsy();
699+
});
700+
});
701+
682702
});
683703

684704
@Component({
@@ -764,6 +784,24 @@ class DynamicTooltipsDemo {
764784
}
765785
}
766786

787+
@Component({
788+
template: `
789+
<input
790+
#input
791+
style="user-select: none; -webkit-user-select: none"
792+
matTooltip="Something">
793+
794+
<textarea
795+
#textarea
796+
style="user-select: none; -webkit-user-select: none"
797+
matTooltip="Another thing"></textarea>
798+
`,
799+
})
800+
class TooltipOnTextFields {
801+
@ViewChild('input') input: ElementRef;
802+
@ViewChild('textarea') textarea: ElementRef;
803+
}
804+
767805
/** Asserts whether a tooltip directive has a tooltip instance. */
768806
function assertTooltipInstance(tooltip: MatTooltip, shouldExist: boolean): void {
769807
// Note that we have to cast this to a boolean, because Jasmine will go into an infinite loop

src/lib/tooltip/tooltip.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ export class MatTooltip implements OnDestroy {
182182
@Inject(MAT_TOOLTIP_SCROLL_STRATEGY) private _scrollStrategy,
183183
@Optional() private _dir: Directionality) {
184184

185+
const element: HTMLElement = _elementRef.nativeElement;
186+
185187
// The mouse events shouldn't be bound on iOS devices, because
186188
// they can prevent the first tap from firing its click event.
187189
if (!_platform.IOS) {
@@ -190,9 +192,16 @@ export class MatTooltip implements OnDestroy {
190192

191193
this._manualListeners
192194
.forEach((listener, event) => _elementRef.nativeElement.addEventListener(event, listener));
195+
} else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
196+
// When we bind a gesture event on an element (in this case `longpress`), HammerJS
197+
// will add some inline styles by default, including `user-select: none`. This is
198+
// problematic on iOS, because it will prevent users from typing in inputs. If
199+
// we're on iOS and the tooltip is attached on an input or textarea, we clear
200+
// the `user-select` to avoid these issues.
201+
element.style.webkitUserSelect = element.style.userSelect = '';
193202
}
194203

195-
_focusMonitor.monitor(_elementRef.nativeElement, false).subscribe(origin => {
204+
_focusMonitor.monitor(element, false).subscribe(origin => {
196205
// Note that the focus monitor runs outside the Angular zone.
197206
if (!origin) {
198207
_ngZone.run(() => this.hide(0));

0 commit comments

Comments
 (0)