mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-26 16:21:55 +08:00
fix(input): only focus the first input / textarea when clicking on the parent item (#22049)
fixes #22037 resolves #22032
This commit is contained in:
14
core/src/components.d.ts
vendored
14
core/src/components.d.ts
vendored
@ -2439,6 +2439,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"`.
|
* 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';
|
"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 `<textarea>` element used under the hood.
|
* Returns the native `<textarea>` element used under the hood.
|
||||||
*/
|
*/
|
||||||
@ -2480,7 +2484,11 @@ export namespace Components {
|
|||||||
*/
|
*/
|
||||||
"rows"?: number;
|
"rows"?: number;
|
||||||
/**
|
/**
|
||||||
* Sets focus on the specified `ion-textarea`. Use this method instead of the global `input.focus()`.
|
* Sets blur on the native `textarea` in `ion-textarea`. Use this method instead of the global `textarea.blur()`.
|
||||||
|
*/
|
||||||
|
"setBlur": () => Promise<void>;
|
||||||
|
/**
|
||||||
|
* Sets focus on the native `textarea` in `ion-textarea`. Use this method instead of the global `textarea.focus()`.
|
||||||
*/
|
*/
|
||||||
"setFocus": () => Promise<void>;
|
"setFocus": () => Promise<void>;
|
||||||
/**
|
/**
|
||||||
@ -5738,6 +5746,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"`.
|
* 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';
|
"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"`.
|
* A hint to the browser for which keyboard to display. Possible values: `"none"`, `"text"`, `"tel"`, `"url"`, `"email"`, `"numeric"`, `"decimal"`, and `"search"`.
|
||||||
*/
|
*/
|
||||||
|
@ -177,9 +177,9 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
|
|||||||
return (this.isClickable() || this.hasCover());
|
return (this.isClickable() || this.hasCover());
|
||||||
}
|
}
|
||||||
|
|
||||||
private hasInputs(): boolean {
|
private getFirstInput(): HTMLIonInputElement | HTMLIonTextareaElement {
|
||||||
const inputs = this.el.querySelectorAll('ion-input');
|
const inputs = this.el.querySelectorAll('ion-input, ion-textarea') as NodeListOf<HTMLIonInputElement | HTMLIonTextareaElement>;
|
||||||
return inputs.length > 0;
|
return inputs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is needed for WebKit due to a delegatesFocus bug where
|
// This is needed for WebKit due to a delegatesFocus bug where
|
||||||
@ -187,17 +187,27 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
|
|||||||
// but is opening the keyboard. It will no longer be needed with
|
// but is opening the keyboard. It will no longer be needed with
|
||||||
// iOS 14.
|
// iOS 14.
|
||||||
@Listen('click')
|
@Listen('click')
|
||||||
delegateFocus() {
|
delegateFocus(ev: Event) {
|
||||||
if (this.hasInputs()) {
|
const clickedItem = (ev.target as HTMLElement).tagName === 'ION-ITEM';
|
||||||
const input = this.el.querySelector('ion-input');
|
const input = this.getFirstInput();
|
||||||
if (input) {
|
let firstActive = false;
|
||||||
input.fireFocusEvents = false;
|
|
||||||
input.setBlur();
|
// If the first input is the same as the active element we need
|
||||||
input.setFocus();
|
// to focus the first input again, but if the active element
|
||||||
raf(() => {
|
// is another input inside of the item we shouldn't switch focus
|
||||||
input.fireFocusEvents = true;
|
if (input && document.activeElement) {
|
||||||
});
|
firstActive = input.querySelector('input, textarea') === document.activeElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only focus the first input if we clicked on an ion-item
|
||||||
|
// and the first input exists
|
||||||
|
if (clickedItem && input && firstActive) {
|
||||||
|
input.fireFocusEvents = false;
|
||||||
|
input.setBlur();
|
||||||
|
input.setFocus();
|
||||||
|
raf(() => {
|
||||||
|
input.fireFocusEvents = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,6 +123,27 @@
|
|||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-list-header>
|
</ion-list-header>
|
||||||
<ion-list class="multiple">
|
<ion-list class="multiple">
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Multiple inputs</ion-label>
|
||||||
|
<ion-input placeholder="Input 1"></ion-input>
|
||||||
|
<ion-input placeholder="Input 2"></ion-input>
|
||||||
|
<ion-input placeholder="Input 3"></ion-input>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Multiple textareas</ion-label>
|
||||||
|
<ion-textarea placeholder="Textarea 1"></ion-textarea>
|
||||||
|
<ion-textarea placeholder="Textarea 2"></ion-textarea>
|
||||||
|
<ion-textarea placeholder="Textarea 3"></ion-textarea>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item>
|
||||||
|
<ion-label>Multiple input/textareas</ion-label>
|
||||||
|
<ion-textarea placeholder="Textarea 1"></ion-textarea>
|
||||||
|
<ion-input placeholder="Input 2"></ion-input>
|
||||||
|
<ion-textarea placeholder="Textarea 3"></ion-textarea>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-checkbox slot="start" id="checkbox-start"></ion-checkbox>
|
<ion-checkbox slot="start" id="checkbox-start"></ion-checkbox>
|
||||||
<ion-label>Multiple inputs w/ cover</ion-label>
|
<ion-label>Multiple inputs w/ cover</ion-label>
|
||||||
@ -179,7 +200,7 @@
|
|||||||
clickableItem.color = color === undefined ? 'primary' : undefined;
|
clickableItem.color = color === undefined ? 'primary' : undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
const inputs = document.querySelectorAll('ion-input');
|
const inputs = document.querySelectorAll('ion-input, ion-textarea');
|
||||||
|
|
||||||
for (var i = 0; i < inputs.length; i++) {
|
for (var i = 0; i < inputs.length; i++) {
|
||||||
const input = inputs[i];
|
const input = inputs[i];
|
||||||
|
@ -315,8 +315,8 @@ Type: `Promise<HTMLTextAreaElement>`
|
|||||||
|
|
||||||
### `setFocus() => Promise<void>`
|
### `setFocus() => Promise<void>`
|
||||||
|
|
||||||
Sets focus on the specified `ion-textarea`. Use this method instead of the global
|
Sets focus on the native `textarea` in `ion-textarea`. Use this method instead of the global
|
||||||
`input.focus()`.
|
`textarea.focus()`.
|
||||||
|
|
||||||
#### Returns
|
#### Returns
|
||||||
|
|
||||||
|
@ -23,6 +23,16 @@ export class Textarea implements ComponentInterface {
|
|||||||
private didBlurAfterEdit = false;
|
private didBlurAfterEdit = false;
|
||||||
private textareaWrapper?: HTMLElement;
|
private textareaWrapper?: HTMLElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
@Element() el!: HTMLElement;
|
@Element() el!: HTMLElement;
|
||||||
|
|
||||||
@State() hasFocus = false;
|
@State() hasFocus = false;
|
||||||
@ -220,8 +230,8 @@ export class Textarea implements ComponentInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets focus on the specified `ion-textarea`. Use this method instead of the global
|
* Sets focus on the native `textarea` in `ion-textarea`. Use this method instead of the global
|
||||||
* `input.focus()`.
|
* `textarea.focus()`.
|
||||||
*/
|
*/
|
||||||
@Method()
|
@Method()
|
||||||
async setFocus() {
|
async setFocus() {
|
||||||
@ -230,6 +240,18 @@ export class Textarea implements ComponentInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets blur on the native `textarea` in `ion-textarea`. Use this method instead of the global
|
||||||
|
* `textarea.blur()`.
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
@Method()
|
||||||
|
async setBlur() {
|
||||||
|
if (this.nativeInput) {
|
||||||
|
this.nativeInput.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the native `<textarea>` element used under the hood.
|
* Returns the native `<textarea>` element used under the hood.
|
||||||
*/
|
*/
|
||||||
@ -296,14 +318,18 @@ export class Textarea implements ComponentInterface {
|
|||||||
this.hasFocus = true;
|
this.hasFocus = true;
|
||||||
this.focusChange();
|
this.focusChange();
|
||||||
|
|
||||||
this.ionFocus.emit(ev);
|
if (this.fireFocusEvents) {
|
||||||
|
this.ionFocus.emit(ev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onBlur = (ev: FocusEvent) => {
|
private onBlur = (ev: FocusEvent) => {
|
||||||
this.hasFocus = false;
|
this.hasFocus = false;
|
||||||
this.focusChange();
|
this.focusChange();
|
||||||
|
|
||||||
this.ionBlur.emit(ev);
|
if (this.fireFocusEvents) {
|
||||||
|
this.ionBlur.emit(ev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private onKeyDown = () => {
|
private onKeyDown = () => {
|
||||||
|
Reference in New Issue
Block a user