mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 11:41:20 +08:00
fix(input): properly focus the input when clicking the item padding in WebKit (#21930)
Related WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=214859 Issue Number: fixes #21509
This commit is contained in:
14
core/src/components.d.ts
vendored
14
core/src/components.d.ts
vendored
@ -869,6 +869,10 @@ export namespace Components {
|
||||
* A hint to the browser for which enter key to display. Possible values: `"enter"`, `"done"`, `"go"`, `"next"`, `"previous"`, `"search"`, and `"send"`.
|
||||
*/
|
||||
"enterkeyhint"?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
|
||||
/**
|
||||
* This is required for a WebKit bug which requires us to blur and focus an input to properly focus the input in an item with delegatesFocus. It will no longer be needed with iOS 14.
|
||||
*/
|
||||
"fireFocusEvents": boolean;
|
||||
/**
|
||||
* Returns the native `<input>` element used under the hood.
|
||||
*/
|
||||
@ -922,7 +926,11 @@ export namespace Components {
|
||||
*/
|
||||
"required": boolean;
|
||||
/**
|
||||
* Sets focus on the specified `ion-input`. Use this method instead of the global `input.focus()`.
|
||||
* Sets blur on the native `input` in `ion-input`. Use this method instead of the global `input.blur()`.
|
||||
*/
|
||||
"setBlur": () => Promise<void>;
|
||||
/**
|
||||
* Sets focus on the native `input` in `ion-input`. Use this method instead of the global `input.focus()`.
|
||||
*/
|
||||
"setFocus": () => Promise<void>;
|
||||
/**
|
||||
@ -4190,6 +4198,10 @@ declare namespace LocalJSX {
|
||||
* A hint to the browser for which enter key to display. Possible values: `"enter"`, `"done"`, `"go"`, `"next"`, `"previous"`, `"search"`, and `"send"`.
|
||||
*/
|
||||
"enterkeyhint"?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send';
|
||||
/**
|
||||
* This is required for a WebKit bug which requires us to blur and focus an input to properly focus the input in an item with delegatesFocus. It will no longer be needed with iOS 14.
|
||||
*/
|
||||
"fireFocusEvents"?: boolean;
|
||||
/**
|
||||
* A hint to the browser for which keyboard to display. Possible values: `"none"`, `"text"`, `"tel"`, `"url"`, `"email"`, `"numeric"`, `"decimal"`, and `"search"`.
|
||||
*/
|
||||
|
@ -23,6 +23,16 @@ export class Input implements ComponentInterface {
|
||||
private didBlurAfterEdit = false;
|
||||
private tabindex?: string | number;
|
||||
|
||||
/**
|
||||
* This is required for a WebKit bug which requires us to
|
||||
* blur and focus an input to properly focus the input in
|
||||
* an item with delegatesFocus. It will no longer be needed
|
||||
* with iOS 14.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
@Prop() fireFocusEvents = true;
|
||||
|
||||
@State() hasFocus = false;
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
@ -244,7 +254,7 @@ export class Input implements ComponentInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets focus on the specified `ion-input`. Use this method instead of the global
|
||||
* Sets focus on the native `input` in `ion-input`. Use this method instead of the global
|
||||
* `input.focus()`.
|
||||
*/
|
||||
@Method()
|
||||
@ -254,6 +264,18 @@ export class Input implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets blur on the native `input` in `ion-input`. Use this method instead of the global
|
||||
* `input.blur()`.
|
||||
* @internal
|
||||
*/
|
||||
@Method()
|
||||
async setBlur() {
|
||||
if (this.nativeInput) {
|
||||
this.nativeInput.blur();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the native `<input>` element used under the hood.
|
||||
*/
|
||||
@ -298,16 +320,20 @@ export class Input implements ComponentInterface {
|
||||
this.focusChanged();
|
||||
this.emitStyle();
|
||||
|
||||
if (this.fireFocusEvents) {
|
||||
this.ionBlur.emit(ev);
|
||||
}
|
||||
}
|
||||
|
||||
private onFocus = (ev: FocusEvent) => {
|
||||
this.hasFocus = true;
|
||||
this.focusChanged();
|
||||
this.emitStyle();
|
||||
|
||||
if (this.fireFocusEvents) {
|
||||
this.ionFocus.emit(ev);
|
||||
}
|
||||
}
|
||||
|
||||
private onKeydown = (ev: KeyboardEvent) => {
|
||||
if (this.shouldClearOnEdit()) {
|
||||
|
@ -345,7 +345,7 @@ Type: `Promise<HTMLInputElement>`
|
||||
|
||||
### `setFocus() => Promise<void>`
|
||||
|
||||
Sets focus on the specified `ion-input`. Use this method instead of the global
|
||||
Sets focus on the native `input` in `ion-input`. Use this method instead of the global
|
||||
`input.focus()`.
|
||||
|
||||
#### Returns
|
||||
|
@ -57,6 +57,7 @@
|
||||
<ion-item tabindex="1">
|
||||
<ion-label position="stacked">Tab 1st</ion-label>
|
||||
<ion-input></ion-input>
|
||||
<ion-input></ion-input>
|
||||
</ion-item>
|
||||
</ion-content>
|
||||
|
||||
@ -69,6 +70,11 @@
|
||||
.md div {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
ion-item {
|
||||
--background: #f6f6f6;
|
||||
--padding-start: 40px;
|
||||
}
|
||||
</style>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
@ -3,6 +3,7 @@ import { Component, ComponentInterface, Element, Host, Listen, Prop, State, forc
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { AnimationBuilder, Color, CssClassMap, RouterDirection, StyleEventDetail } from '../../interface';
|
||||
import { AnchorInterface, ButtonInterface } from '../../utils/element-interface';
|
||||
import { raf } from '../../utils/helpers';
|
||||
import { createColorClasses, hostContext, openURL } from '../../utils/theme';
|
||||
|
||||
/**
|
||||
@ -176,6 +177,30 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
|
||||
return (this.isClickable() || this.hasCover());
|
||||
}
|
||||
|
||||
private hasInputs(): boolean {
|
||||
const inputs = this.el.querySelectorAll('ion-input');
|
||||
return inputs.length > 0;
|
||||
}
|
||||
|
||||
// This is needed for WebKit due to a delegatesFocus bug where
|
||||
// clicking on the left padding of an item is not focusing the input
|
||||
// but is opening the keyboard. It will no longer be needed with
|
||||
// iOS 14.
|
||||
@Listen('click')
|
||||
delegateFocus() {
|
||||
if (this.hasInputs()) {
|
||||
const input = this.el.querySelector('ion-input');
|
||||
if (input) {
|
||||
input.fireFocusEvents = false;
|
||||
input.setBlur();
|
||||
input.setFocus();
|
||||
raf(() => {
|
||||
input.fireFocusEvents = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { detail, detailIcon, download, lines, disabled, href, rel, target, routerAnimation, routerDirection } = this;
|
||||
const childStyles = {};
|
||||
|
@ -179,6 +179,19 @@
|
||||
clickableItem.color = color === undefined ? 'primary' : undefined;
|
||||
});
|
||||
|
||||
const inputs = document.querySelectorAll('ion-input');
|
||||
|
||||
for (var i = 0; i < inputs.length; i++) {
|
||||
const input = inputs[i];
|
||||
|
||||
input.addEventListener('ionBlur', function() {
|
||||
console.log('Listen ionBlur: fired');
|
||||
});
|
||||
|
||||
input.addEventListener('ionFocus', function() {
|
||||
console.log('Listen ionFocus: fired');
|
||||
});
|
||||
}
|
||||
|
||||
function toggleDisabled() {
|
||||
isDisabled = !isDisabled;
|
||||
|
Reference in New Issue
Block a user