Skip to content

Commit 2b015b2

Browse files
authored
fix(input, searchbar, textarea): ensure nativeInput is always available (#28362)
Issue number: resolves #28283 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> `getInputElement()` is used to access the native input. If the component has yet to render, then the function will return `undefined`. This happens mostly when using `ref` on React. ```tsx <IonInput ref={async input => { const nativeInput = await input.getInputElement(); // nativeInput is undefined }} /> ``` ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - `getInputElement()` will wait to return once the component is ready. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> Dev build: `7.5.1-dev.11697488622.175c9183`
1 parent 15a0225 commit 2b015b2

File tree

3 files changed

+39
-6
lines changed

3 files changed

+39
-6
lines changed

core/src/components/input/input.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,13 @@ import { Build, Component, Element, Event, Host, Method, Prop, State, Watch, for
33
import type { LegacyFormController, NotchController } from '@utils/forms';
44
import { createLegacyFormController, createNotchController } from '@utils/forms';
55
import type { Attributes } from '@utils/helpers';
6-
import { inheritAriaAttributes, debounceEvent, findItemLabel, inheritAttributes } from '@utils/helpers';
6+
import {
7+
inheritAriaAttributes,
8+
debounceEvent,
9+
findItemLabel,
10+
inheritAttributes,
11+
componentOnReady,
12+
} from '@utils/helpers';
713
import { printIonWarning } from '@utils/logging';
814
import { createSlotMutationController } from '@utils/slot-mutation-controller';
915
import type { SlotMutationController } from '@utils/slot-mutation-controller';
@@ -430,7 +436,14 @@ export class Input implements ComponentInterface {
430436
* Returns the native `<input>` element used under the hood.
431437
*/
432438
@Method()
433-
getInputElement(): Promise<HTMLInputElement> {
439+
async getInputElement(): Promise<HTMLInputElement> {
440+
/**
441+
* If this gets called in certain early lifecycle hooks (ex: Vue onMounted),
442+
* nativeInput won't be defined yet with the custom elements build, so wait for it to load in.
443+
*/
444+
if (!this.nativeInput) {
445+
await new Promise((resolve) => componentOnReady(this.el, resolve));
446+
}
434447
return Promise.resolve(this.nativeInput!);
435448
}
436449

core/src/components/searchbar/searchbar.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ComponentInterface, EventEmitter } from '@stencil/core';
22
import { Component, Element, Event, Host, Method, Prop, State, Watch, forceUpdate, h } from '@stencil/core';
3-
import { debounceEvent, raf } from '@utils/helpers';
3+
import { debounceEvent, raf, componentOnReady } from '@utils/helpers';
44
import { isRTL } from '@utils/rtl';
55
import { createColorClasses } from '@utils/theme';
66
import { arrowBackSharp, closeCircle, closeSharp, searchOutline, searchSharp } from 'ionicons/icons';
@@ -269,7 +269,14 @@ export class Searchbar implements ComponentInterface {
269269
* Returns the native `<input>` element used under the hood.
270270
*/
271271
@Method()
272-
getInputElement(): Promise<HTMLInputElement> {
272+
async getInputElement(): Promise<HTMLInputElement> {
273+
/**
274+
* If this gets called in certain early lifecycle hooks (ex: Vue onMounted),
275+
* nativeInput won't be defined yet with the custom elements build, so wait for it to load in.
276+
*/
277+
if (!this.nativeInput) {
278+
await new Promise((resolve) => componentOnReady(this.el, resolve));
279+
}
273280
return Promise.resolve(this.nativeInput!);
274281
}
275282

core/src/components/textarea/textarea.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@ import {
1616
import type { LegacyFormController, NotchController } from '@utils/forms';
1717
import { createLegacyFormController, createNotchController } from '@utils/forms';
1818
import type { Attributes } from '@utils/helpers';
19-
import { inheritAriaAttributes, debounceEvent, findItemLabel, inheritAttributes } from '@utils/helpers';
19+
import {
20+
inheritAriaAttributes,
21+
debounceEvent,
22+
findItemLabel,
23+
inheritAttributes,
24+
componentOnReady,
25+
} from '@utils/helpers';
2026
import { printIonWarning } from '@utils/logging';
2127
import { createSlotMutationController } from '@utils/slot-mutation-controller';
2228
import type { SlotMutationController } from '@utils/slot-mutation-controller';
@@ -378,7 +384,14 @@ export class Textarea implements ComponentInterface {
378384
* Returns the native `<textarea>` element used under the hood.
379385
*/
380386
@Method()
381-
getInputElement(): Promise<HTMLTextAreaElement> {
387+
async getInputElement(): Promise<HTMLTextAreaElement> {
388+
/**
389+
* If this gets called in certain early lifecycle hooks (ex: Vue onMounted),
390+
* nativeInput won't be defined yet with the custom elements build, so wait for it to load in.
391+
*/
392+
if (!this.nativeInput) {
393+
await new Promise((resolve) => componentOnReady(this.el, resolve));
394+
}
382395
return Promise.resolve(this.nativeInput!);
383396
}
384397

0 commit comments

Comments
 (0)