mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-10 00:27:41 +08:00
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`
This commit is contained in:
@ -532,7 +532,7 @@ export class Input implements ComponentInterface {
|
|||||||
* Clear the input if the control has not been previously cleared during focus.
|
* Clear the input if the control has not been previously cleared during focus.
|
||||||
* Do not clear if the user hitting enter to submit a form.
|
* Do not clear if the user hitting enter to submit a form.
|
||||||
*/
|
*/
|
||||||
if (!this.didInputClearOnEdit && this.hasValue() && ev.key !== 'Enter') {
|
if (!this.didInputClearOnEdit && this.hasValue() && ev.key !== 'Enter' && ev.key !== 'Tab') {
|
||||||
this.value = '';
|
this.value = '';
|
||||||
this.emitInputChange(ev);
|
this.emitInputChange(ev);
|
||||||
}
|
}
|
||||||
|
|||||||
57
core/src/components/input/test/basic/index.html
Normal file
57
core/src/components/input/test/basic/index.html
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" dir="ltr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Input - Basic</title>
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||||
|
/>
|
||||||
|
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||||
|
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||||
|
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||||
|
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||||
|
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||||
|
<style>
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(5, minmax(250px, 1fr));
|
||||||
|
grid-row-gap: 20px;
|
||||||
|
grid-column-gap: 20px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
|
color: #6f7378;
|
||||||
|
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
@media screen and (max-width: 800px) {
|
||||||
|
.grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<ion-app>
|
||||||
|
<ion-header>
|
||||||
|
<ion-toolbar>
|
||||||
|
<ion-title>Input - Basic</ion-title>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
|
||||||
|
<ion-content id="content" class="ion-padding">
|
||||||
|
<div class="grid">
|
||||||
|
<div class="grid-item">
|
||||||
|
<h2>Default</h2>
|
||||||
|
<ion-input value="hi@ionic.io" label="Email"></ion-input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ion-content>
|
||||||
|
</ion-app>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
43
core/src/components/input/test/clear-on-edit/input.e2e.ts
Normal file
43
core/src/components/input/test/clear-on-edit/input.e2e.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { expect } from '@playwright/test';
|
||||||
|
import { test, configs } from '@utils/test/playwright';
|
||||||
|
|
||||||
|
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||||
|
test.describe(title('input: clearOnEdit'), () => {
|
||||||
|
test('should clear when typed into', async ({ page }) => {
|
||||||
|
await page.setContent(`<ion-input value="abc" clear-on-edit="true" aria-label="input"></ion-input>`, config);
|
||||||
|
|
||||||
|
const ionInput = await page.spyOnEvent('ionInput');
|
||||||
|
|
||||||
|
const input = page.locator('ion-input');
|
||||||
|
await input.locator('input').type('h');
|
||||||
|
|
||||||
|
await ionInput.next();
|
||||||
|
|
||||||
|
await expect(input).toHaveJSProperty('value', 'h');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not clear when enter is pressed', async ({ page }) => {
|
||||||
|
await page.setContent(`<ion-input value="abc" clear-on-edit="true" aria-label="input"></ion-input>`, config);
|
||||||
|
|
||||||
|
const input = page.locator('ion-input');
|
||||||
|
await input.locator('input').focus();
|
||||||
|
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
await page.waitForChanges();
|
||||||
|
|
||||||
|
await expect(input).toHaveJSProperty('value', 'abc');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not clear when tab is pressed', async ({ page }) => {
|
||||||
|
await page.setContent(`<ion-input value="abc" clear-on-edit="true" aria-label="input"></ion-input>`, config);
|
||||||
|
|
||||||
|
const input = page.locator('ion-input');
|
||||||
|
await input.locator('input').focus();
|
||||||
|
|
||||||
|
await page.keyboard.press('Tab');
|
||||||
|
await page.waitForChanges();
|
||||||
|
|
||||||
|
await expect(input).toHaveJSProperty('value', 'abc');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
import { expect } from '@playwright/test';
|
||||||
|
import { test, configs } from '@utils/test/playwright';
|
||||||
|
|
||||||
|
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||||
|
test.describe(title('textarea: clearOnEdit'), () => {
|
||||||
|
test('should clear when typed into', async ({ page }) => {
|
||||||
|
await page.setContent(
|
||||||
|
`<ion-textarea value="abc" clear-on-edit="true" aria-label="textarea"></ion-textarea>`,
|
||||||
|
config
|
||||||
|
);
|
||||||
|
|
||||||
|
const ionInput = await page.spyOnEvent('ionInput');
|
||||||
|
|
||||||
|
const textarea = page.locator('ion-textarea');
|
||||||
|
await textarea.locator('textarea').type('h');
|
||||||
|
|
||||||
|
await ionInput.next();
|
||||||
|
|
||||||
|
await expect(textarea).toHaveJSProperty('value', 'h');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not clear when tab is pressed', async ({ page }) => {
|
||||||
|
await page.setContent(
|
||||||
|
`<ion-textarea value="abc" clear-on-edit="true" aria-label="textarea"></ion-textarea>`,
|
||||||
|
config
|
||||||
|
);
|
||||||
|
|
||||||
|
const textarea = page.locator('ion-textarea');
|
||||||
|
await textarea.locator('textarea').focus();
|
||||||
|
|
||||||
|
await page.keyboard.press('Tab');
|
||||||
|
await page.waitForChanges();
|
||||||
|
|
||||||
|
await expect(textarea).toHaveJSProperty('value', 'abc');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -434,7 +434,7 @@ export class Textarea implements ComponentInterface {
|
|||||||
/**
|
/**
|
||||||
* Check if we need to clear the text input if clearOnEdit is enabled
|
* Check if we need to clear the text input if clearOnEdit is enabled
|
||||||
*/
|
*/
|
||||||
private checkClearOnEdit(ev: Event) {
|
private checkClearOnEdit(ev: KeyboardEvent) {
|
||||||
if (!this.clearOnEdit) {
|
if (!this.clearOnEdit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -442,7 +442,7 @@ export class Textarea implements ComponentInterface {
|
|||||||
* Clear the textarea if the control has not been previously cleared
|
* Clear the textarea if the control has not been previously cleared
|
||||||
* during focus.
|
* during focus.
|
||||||
*/
|
*/
|
||||||
if (!this.didTextareaClearOnEdit && this.hasValue()) {
|
if (!this.didTextareaClearOnEdit && this.hasValue() && ev.key !== 'Tab') {
|
||||||
this.value = '';
|
this.value = '';
|
||||||
this.emitInputChange(ev);
|
this.emitInputChange(ev);
|
||||||
}
|
}
|
||||||
@ -501,7 +501,7 @@ export class Textarea implements ComponentInterface {
|
|||||||
this.ionBlur.emit(ev);
|
this.ionBlur.emit(ev);
|
||||||
};
|
};
|
||||||
|
|
||||||
private onKeyDown = (ev: Event) => {
|
private onKeyDown = (ev: KeyboardEvent) => {
|
||||||
this.checkClearOnEdit(ev);
|
this.checkClearOnEdit(ev);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user