Skip to content

Commit 9469b4f

Browse files
committed
feat(input): clearOnEdit feature. Closes #9187
1 parent 91f5087 commit 9469b4f

File tree

6 files changed

+143
-0
lines changed

6 files changed

+143
-0
lines changed

src/components/input/input-base.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ export class InputBase extends Ion {
3232
_nav: NavControllerBase;
3333
_native: NativeInput;
3434

35+
// Whether to clear after the user returns to the input and resumes editing
36+
_clearOnEdit: boolean;
37+
// A tracking flag to watch for the blur after editing to help with clearOnEdit
38+
_didBlurAfterEdit: boolean;
39+
3540
inputControl: NgControl;
3641

3742
constructor(
@@ -133,6 +138,33 @@ export class InputBase extends Ion {
133138
this._native && this._native.isDisabled(this._disabled);
134139
}
135140

141+
setClearOnEdit(val: boolean) {
142+
this._clearOnEdit = isTrueProperty(val);
143+
}
144+
145+
/**
146+
* Check if we need to clear the text input if clearOnEdit is enabled
147+
* @private
148+
*/
149+
checkClearOnEdit(inputValue: string) {
150+
if(!this._clearOnEdit) { return; }
151+
152+
// Did the input value change after it was blurred and edited?
153+
if (this._didBlurAfterEdit && this.hasValue()) {
154+
// Clear the input
155+
this.clearTextInput();
156+
}
157+
158+
// Reset the flag
159+
this._didBlurAfterEdit = false;
160+
}
161+
162+
/**
163+
* Overriden in child input
164+
* @private
165+
*/
166+
clearTextInput() {}
167+
136168
/**
137169
* @private
138170
*/
@@ -147,6 +179,10 @@ export class InputBase extends Ion {
147179
this.onChange(inputValue);
148180
});
149181

182+
nativeInput.keydown.subscribe((inputValue: any) => {
183+
this.onKeydown(inputValue);
184+
});
185+
150186
this.focusChange(this.hasFocus());
151187
nativeInput.focusChange.subscribe((textInputHasFocus: any) => {
152188
this.focusChange(textInputHasFocus);
@@ -228,6 +264,16 @@ export class InputBase extends Ion {
228264
this.checkHasValue(val);
229265
}
230266

267+
/**
268+
* onKeydown handler for clearOnEdit
269+
* @private
270+
*/
271+
onKeydown(val: any) {
272+
if(this._clearOnEdit) {
273+
this.checkClearOnEdit(val);
274+
}
275+
}
276+
231277
/**
232278
* @private
233279
*/
@@ -241,12 +287,21 @@ export class InputBase extends Ion {
241287
return this._native.hasFocus();
242288
}
243289

290+
/**
291+
* @private
292+
*/
293+
hasValue(): boolean {
294+
let inputValue = this._value;
295+
return (inputValue !== null && inputValue !== undefined && inputValue !== '');
296+
}
297+
244298
/**
245299
* @private
246300
*/
247301
checkHasValue(inputValue: any) {
248302
if (this._item) {
249303
let hasValue = (inputValue !== null && inputValue !== undefined && inputValue !== '');
304+
250305
this._item.setElementClass('input-has-value', hasValue);
251306
}
252307
}
@@ -260,6 +315,12 @@ export class InputBase extends Ion {
260315
}
261316
if (!inputHasFocus) {
262317
this.deregScrollMove();
318+
319+
}
320+
321+
// If clearOnEdit is enabled and the input blurred but has a value, set a flag
322+
if(this._clearOnEdit && !inputHasFocus && this.hasValue()) {
323+
this._didBlurAfterEdit = true;
263324
}
264325
}
265326

src/components/input/input.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,18 @@ export class TextInput extends InputBase {
160160
this._setMode(val);
161161
}
162162

163+
/**
164+
* @input {boolean} whether to clear the input upon editing or not
165+
*/
166+
@Input()
167+
get clearOnEdit() {
168+
return this._clearOnEdit;
169+
}
170+
set clearOnEdit(val: any) {
171+
super.setClearOnEdit(val);
172+
}
173+
174+
163175
/**
164176
* @private
165177
*/
@@ -207,6 +219,11 @@ export class TextInput extends InputBase {
207219
this._item.setElementClass('item-input', true);
208220
this._item.registerInput(this._type);
209221
}
222+
223+
// By default, password inputs clear after focus when they have content
224+
if(this.type === 'password' && this.clearOnEdit !== false) {
225+
this.clearOnEdit = true;
226+
}
210227
}
211228

212229
/**

src/components/input/native-input.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export class NativeInput {
1919

2020
@Output() focusChange: EventEmitter<boolean> = new EventEmitter<boolean>();
2121
@Output() valueChange: EventEmitter<string> = new EventEmitter<string>();
22+
@Output() keydown: EventEmitter<string> = new EventEmitter<string>();
2223

2324
constructor(
2425
public _elementRef: ElementRef,
@@ -34,6 +35,13 @@ export class NativeInput {
3435
_change(ev: any) {
3536
this.valueChange.emit(ev.target.value);
3637
}
38+
39+
@HostListener('keydown', ['$event'])
40+
_keyDown(ev: any) {
41+
if(ev) {
42+
ev.target && this.keydown.emit(ev.target.value);
43+
}
44+
}
3745

3846
@HostListener('focus')
3947
_focus() {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Component, NgModule } from '@angular/core';
2+
import { IonicApp, IonicModule } from '../../../..';
3+
4+
5+
@Component({
6+
templateUrl: 'main.html'
7+
})
8+
export class E2EPage {
9+
myValue = '';
10+
myValue2 = '';
11+
}
12+
13+
@Component({
14+
template: '<ion-nav [root]="rootPage"></ion-nav>'
15+
})
16+
export class E2EApp {
17+
rootPage = E2EPage;
18+
}
19+
20+
@NgModule({
21+
declarations: [
22+
E2EApp,
23+
E2EPage
24+
],
25+
imports: [
26+
IonicModule.forRoot(E2EApp)
27+
],
28+
bootstrap: [IonicApp],
29+
entryComponents: [
30+
E2EPage
31+
]
32+
})
33+
export class AppModule {}

src/components/input/test/clear-after-edit/e2e.ts

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<ion-header>
2+
3+
<ion-toolbar>
4+
<ion-title>Clear After Edit</ion-title>
5+
</ion-toolbar>
6+
7+
</ion-header>
8+
9+
10+
<ion-content>
11+
12+
<ion-list>
13+
14+
<ion-item>
15+
<ion-label>Email</ion-label>
16+
<ion-input class="e2eClearInput" [(ngModel)]="myValue2" type="email"></ion-input>
17+
</ion-item>
18+
<ion-item>
19+
<ion-label>Password</ion-label>
20+
<ion-input class="e2eClearInput" [(ngModel)]="myValue" type="password"></ion-input>
21+
</ion-item>
22+
</ion-list>
23+
24+
</ion-content>

0 commit comments

Comments
 (0)