feat(inputs) debounce input and change events (#13764)

* feat(helpers) add debounce helper

* feat(searchbar) debounce ionInput

* feat(range) debounce ionChange

* feat(input) debouce ionInput

* feat(textarea) debounce ionInput

* feat(range) make debounceChange private

* feat(searchbar) make debounceInput private

* feat(inputs) change default debounce to 0 in input/textarea
This commit is contained in:
Cam Wiegert
2018-01-04 15:07:50 -06:00
committed by GitHub
parent 0273cb2a20
commit 7f8cf42773
8 changed files with 109 additions and 16 deletions

View File

@ -1155,6 +1155,7 @@ declare global {
checked?: boolean;
clearInput?: boolean;
clearOnEdit?: boolean;
debounce?: number;
disabled?: boolean;
inputmode?: string;
max?: string;
@ -2880,6 +2881,7 @@ declare global {
autofocus?: boolean;
clearOnEdit?: boolean;
cols?: number;
debounce?: number;
disabled?: boolean;
maxlength?: number;
minlength?: number;

View File

@ -1,5 +1,6 @@
import { Component, Element, Event, EventEmitter, Prop, PropDidChange } from '@stencil/core';
import { debounce } from '../../utils/helpers';
import { createThemedClasses } from '../../utils/theme';
import { InputComponent } from './input-base';
@ -23,6 +24,11 @@ export class Input implements InputComponent {
@Element() private el: HTMLElement;
/**
* @output {Event} Emitted when the input value has changed.
*/
@Event() ionInput: EventEmitter;
/**
* @output {Event} Emitted when the styles change.
*/
@ -83,6 +89,18 @@ export class Input implements InputComponent {
*/
@Prop({ mutable: true }) clearOnEdit: boolean;
/**
* @input {number} Set the amount of time, in milliseconds, to wait to trigger the `ionInput` event after each keystroke. Default `0`.
*/
@Prop() debounce: number = 0;
@PropDidChange('debounce')
private debounceInput() {
this.ionInput.emit = debounce(
this.ionInput.emit.bind(this.ionInput),
this.debounce
);
}
/**
* @input {boolean} If true, the user cannot interact with the input. Defaults to `false`.
*/
@ -192,6 +210,7 @@ export class Input implements InputComponent {
componentDidLoad() {
this.debounceInput();
this.emitStyle();
// By default, password inputs clear after focus when they have content
@ -225,6 +244,7 @@ export class Input implements InputComponent {
inputChanged(ev: any) {
this.value = ev.target && ev.target.value;
this.ionInput.emit(ev);
this.emitStyle();
}
@ -242,15 +262,15 @@ export class Input implements InputComponent {
}
}
inputKeydown() {
this.checkClearOnEdit();
inputKeydown(ev: any) {
this.checkClearOnEdit(ev);
}
/**
* Check if we need to clear the text input if clearOnEdit is enabled
*/
checkClearOnEdit() {
checkClearOnEdit(ev: any) {
if (!this.clearOnEdit) {
return;
}
@ -258,15 +278,16 @@ export class Input implements InputComponent {
// Did the input value change after it was blurred and edited?
if (this.didBlurAfterEdit && this.hasValue()) {
// Clear the input
this.clearTextInput();
this.clearTextInput(ev);
}
// Reset the flag
this.didBlurAfterEdit = false;
}
clearTextInput() {
clearTextInput(ev: any) {
this.value = '';
this.ionInput.emit(ev);
}
hasFocus(): boolean {

View File

@ -47,6 +47,11 @@ boolean
boolean
#### debounce
number
#### disabled
boolean
@ -179,6 +184,11 @@ boolean
boolean
#### debounce
number
#### disabled
boolean
@ -277,6 +287,9 @@ string
#### ionFocus
#### ionInput
#### ionStyle

View File

@ -1,6 +1,6 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop, PropDidChange, State } from '@stencil/core';
import { BaseInputComponent, GestureDetail } from '../../index';
import { clamp } from '../../utils/helpers';
import { clamp, debounce } from '../../utils/helpers';
@Component({
tag: 'ion-range',
@ -75,6 +75,13 @@ export class Range implements BaseInputComponent {
* `ionChange` event after each change in the range value. Default `0`.
*/
@Prop() debounce: number = 0;
@PropDidChange('debounce')
private debounceChange() {
this.ionChange.emit = debounce(
this.ionChange.emit.bind(this.ionChange),
this.debounce
);
}
/*
* @input {boolean} If true, the user cannot interact with the range. Default false.
@ -126,13 +133,14 @@ export class Range implements BaseInputComponent {
@PropDidChange('value')
protected valueChanged(val: boolean) {
setTimeout(() => this.ionChange.emit({value: val}), this.debounce);
this.ionChange.emit({value: val});
this.emitStyle();
}
componentWillLoad() {
this.inputUpdated();
this.createTicks();
this.debounceChange();
this.emitStyle();
}

View File

@ -1,4 +1,5 @@
import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core';
import { Component, Element, Event, EventEmitter, Prop, PropDidChange, State } from '@stencil/core';
import { debounce } from '../../utils/helpers';
@Component({
@ -86,6 +87,13 @@ export class Searchbar {
* @input {number} Set the amount of time, in milliseconds, to wait to trigger the `ionInput` event after each keystroke. Default `250`.
*/
@Prop({ mutable: true }) debounce: number = 250;
@PropDidChange('debounce')
private debounceInput() {
this.ionInput.emit = debounce(
this.ionInput.emit.bind(this.ionInput),
this.debounce
);
}
/**
* @input {string} Set the input's placeholder. Default `"Search"`.
@ -115,6 +123,7 @@ export class Searchbar {
componentDidLoad() {
this.positionElements();
this.debounceInput();
}
/**
@ -153,9 +162,7 @@ export class Searchbar {
*/
inputChanged(ev: any) {
this.value = ev.target.value;
setTimeout(() => {
this.ionInput.emit(ev);
}, this.debounce);
}
inputUpdated() {

View File

@ -66,6 +66,11 @@ boolean
number
#### debounce
number
#### disabled
boolean
@ -148,6 +153,11 @@ boolean
number
#### debounce
number
#### disabled
boolean
@ -211,6 +221,9 @@ string
#### ionFocus
#### ionInput
#### ionStyle

View File

@ -1,5 +1,6 @@
import { Component, Element, Event, EventEmitter, Prop, PropDidChange } from '@stencil/core';
import { debounce } from '../../utils/helpers';
import { createThemedClasses } from '../../utils/theme';
import { TextareaComponent } from '../input/input-base';
@ -29,6 +30,11 @@ export class Textarea implements TextareaComponent {
@Element() private el: HTMLElement;
/**
* @output {Event} Emitted when the input value has changed.
*/
@Event() ionInput: EventEmitter;
/**
* @output {Event} Emitted when the styles change.
*/
@ -64,6 +70,18 @@ export class Textarea implements TextareaComponent {
*/
@Prop({ mutable: true }) clearOnEdit: boolean;
/**
* @input {number} Set the amount of time, in milliseconds, to wait to trigger the `ionInput` event after each keystroke. Default `0`.
*/
@Prop() debounce: number = 0;
@PropDidChange('debounce')
private debounceInput() {
this.ionInput.emit = debounce(
this.ionInput.emit.bind(this.ionInput),
this.debounce
);
}
/**
* @input {boolean} If true, the user cannot interact with the textarea. Defaults to `false`.
*/
@ -141,6 +159,7 @@ export class Textarea implements TextareaComponent {
}
componentDidLoad() {
this.debounceInput();
this.emitStyle();
}
@ -160,8 +179,9 @@ export class Textarea implements TextareaComponent {
});
}
clearTextInput() {
clearTextInput(ev: any) {
this.value = '';
this.ionInput.emit(ev);
}
inputBlurred(ev: any) {
@ -173,6 +193,7 @@ export class Textarea implements TextareaComponent {
inputChanged(ev: any) {
this.value = ev.target && ev.target.value;
this.ionInput.emit(ev);
this.emitStyle();
}
@ -183,14 +204,14 @@ export class Textarea implements TextareaComponent {
this.emitStyle();
}
inputKeydown() {
this.checkClearOnEdit();
inputKeydown(ev: any) {
this.checkClearOnEdit(ev);
}
/**
* Check if we need to clear the text input if clearOnEdit is enabled
*/
checkClearOnEdit() {
checkClearOnEdit(ev: any) {
if (!this.clearOnEdit) {
return;
}
@ -198,7 +219,7 @@ export class Textarea implements TextareaComponent {
// Did the input value change after it was blurred and edited?
if (this.didBlurAfterEdit && this.hasValue()) {
// Clear the input
this.clearTextInput();
this.clearTextInput(ev);
}
// Reset the flag

View File

@ -295,3 +295,11 @@ export function domControllerAsync(domControllerFunction: Function, callback?: F
});
});
}
export function debounce(func: Function, wait: number = 250) {
let timer: number;
return (...args: any[]): void => {
clearTimeout(timer);
timer = setTimeout(func, wait, ...args);
};
}