Skip to content

Commit 444acc1

Browse files
authored
fix(input, textarea): clearOnEdit does not clear when pressing Tab (#28005)
Issue number: resolves #27746 --------- <!-- 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. --> Pressing the Tab key when focused on an input/textarea with `clearOnEdit` clears the text field and then moves focus to the next focusable element. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - Pressing the Tab key does not clear the text field even when clearOnEdit is enabled. - Added test coverage - I also noticed that input did not have an `index.html` file in the basic directory, so I added that. ## 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.3.1-dev.11692202566.13cd16c4`
1 parent bbfb8f8 commit 444acc1

File tree

5 files changed

+141
-4
lines changed

5 files changed

+141
-4
lines changed

core/src/components/input/input.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ export class Input implements ComponentInterface {
532532
* Clear the input if the control has not been previously cleared during focus.
533533
* Do not clear if the user hitting enter to submit a form.
534534
*/
535-
if (!this.didInputClearOnEdit && this.hasValue() && ev.key !== 'Enter') {
535+
if (!this.didInputClearOnEdit && this.hasValue() && ev.key !== 'Enter' && ev.key !== 'Tab') {
536536
this.value = '';
537537
this.emitInputChange(ev);
538538
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<!DOCTYPE html>
2+
<html lang="en" dir="ltr">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Input - Basic</title>
6+
<meta
7+
name="viewport"
8+
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
9+
/>
10+
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
11+
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
12+
<script src="../../../../../scripts/testing/scripts.js"></script>
13+
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
14+
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
15+
<style>
16+
.grid {
17+
display: grid;
18+
grid-template-columns: repeat(5, minmax(250px, 1fr));
19+
grid-row-gap: 20px;
20+
grid-column-gap: 20px;
21+
}
22+
h2 {
23+
font-size: 12px;
24+
font-weight: normal;
25+
26+
color: #6f7378;
27+
28+
margin-top: 10px;
29+
}
30+
@media screen and (max-width: 800px) {
31+
.grid {
32+
grid-template-columns: 1fr;
33+
padding: 0;
34+
}
35+
}
36+
</style>
37+
</head>
38+
39+
<body>
40+
<ion-app>
41+
<ion-header>
42+
<ion-toolbar>
43+
<ion-title>Input - Basic</ion-title>
44+
</ion-toolbar>
45+
</ion-header>
46+
47+
<ion-content id="content" class="ion-padding">
48+
<div class="grid">
49+
<div class="grid-item">
50+
<h2>Default</h2>
51+
<ion-input value="[email protected]" label="Email"></ion-input>
52+
</div>
53+
</div>
54+
</ion-content>
55+
</ion-app>
56+
</body>
57+
</html>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { expect } from '@playwright/test';
2+
import { test, configs } from '@utils/test/playwright';
3+
4+
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
5+
test.describe(title('input: clearOnEdit'), () => {
6+
test('should clear when typed into', async ({ page }) => {
7+
await page.setContent(`<ion-input value="abc" clear-on-edit="true" aria-label="input"></ion-input>`, config);
8+
9+
const ionInput = await page.spyOnEvent('ionInput');
10+
11+
const input = page.locator('ion-input');
12+
await input.locator('input').type('h');
13+
14+
await ionInput.next();
15+
16+
await expect(input).toHaveJSProperty('value', 'h');
17+
});
18+
19+
test('should not clear when enter is pressed', async ({ page }) => {
20+
await page.setContent(`<ion-input value="abc" clear-on-edit="true" aria-label="input"></ion-input>`, config);
21+
22+
const input = page.locator('ion-input');
23+
await input.locator('input').focus();
24+
25+
await page.keyboard.press('Enter');
26+
await page.waitForChanges();
27+
28+
await expect(input).toHaveJSProperty('value', 'abc');
29+
});
30+
31+
test('should not clear when tab is pressed', async ({ page }) => {
32+
await page.setContent(`<ion-input value="abc" clear-on-edit="true" aria-label="input"></ion-input>`, config);
33+
34+
const input = page.locator('ion-input');
35+
await input.locator('input').focus();
36+
37+
await page.keyboard.press('Tab');
38+
await page.waitForChanges();
39+
40+
await expect(input).toHaveJSProperty('value', 'abc');
41+
});
42+
});
43+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { expect } from '@playwright/test';
2+
import { test, configs } from '@utils/test/playwright';
3+
4+
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
5+
test.describe(title('textarea: clearOnEdit'), () => {
6+
test('should clear when typed into', async ({ page }) => {
7+
await page.setContent(
8+
`<ion-textarea value="abc" clear-on-edit="true" aria-label="textarea"></ion-textarea>`,
9+
config
10+
);
11+
12+
const ionInput = await page.spyOnEvent('ionInput');
13+
14+
const textarea = page.locator('ion-textarea');
15+
await textarea.locator('textarea').type('h');
16+
17+
await ionInput.next();
18+
19+
await expect(textarea).toHaveJSProperty('value', 'h');
20+
});
21+
22+
test('should not clear when tab is pressed', async ({ page }) => {
23+
await page.setContent(
24+
`<ion-textarea value="abc" clear-on-edit="true" aria-label="textarea"></ion-textarea>`,
25+
config
26+
);
27+
28+
const textarea = page.locator('ion-textarea');
29+
await textarea.locator('textarea').focus();
30+
31+
await page.keyboard.press('Tab');
32+
await page.waitForChanges();
33+
34+
await expect(textarea).toHaveJSProperty('value', 'abc');
35+
});
36+
});
37+
});

core/src/components/textarea/textarea.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,15 +434,15 @@ export class Textarea implements ComponentInterface {
434434
/**
435435
* Check if we need to clear the text input if clearOnEdit is enabled
436436
*/
437-
private checkClearOnEdit(ev: Event) {
437+
private checkClearOnEdit(ev: KeyboardEvent) {
438438
if (!this.clearOnEdit) {
439439
return;
440440
}
441441
/**
442442
* Clear the textarea if the control has not been previously cleared
443443
* during focus.
444444
*/
445-
if (!this.didTextareaClearOnEdit && this.hasValue()) {
445+
if (!this.didTextareaClearOnEdit && this.hasValue() && ev.key !== 'Tab') {
446446
this.value = '';
447447
this.emitInputChange(ev);
448448
}
@@ -501,7 +501,7 @@ export class Textarea implements ComponentInterface {
501501
this.ionBlur.emit(ev);
502502
};
503503

504-
private onKeyDown = (ev: Event) => {
504+
private onKeyDown = (ev: KeyboardEvent) => {
505505
this.checkClearOnEdit(ev);
506506
};
507507

0 commit comments

Comments
 (0)