mirror of
https://github.com/discourse/discourse.git
synced 2025-05-25 00:32:52 +08:00
DEV: Support for onChange
on {{text-field}}
(#9362)
* DEV: Support for `onChange` on `{{text-field}}` This will automatically be debounced and only fired when the value changes. There is also `onChangeImmediate` which is not debounced in case you need that, but in almost all cases when observing text in an element you should debounce. * Add cancel for timer
This commit is contained in:
@ -1,8 +1,14 @@
|
|||||||
import { TextField } from "@ember/component";
|
import { TextField } from "@ember/component";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import { siteDir, isRTL, isLTR } from "discourse/lib/text-direction";
|
import { siteDir, isRTL, isLTR } from "discourse/lib/text-direction";
|
||||||
|
import { next, debounce, cancel } from "@ember/runloop";
|
||||||
|
|
||||||
|
const DEBOUNCE_MS = 500;
|
||||||
|
|
||||||
export default TextField.extend({
|
export default TextField.extend({
|
||||||
|
_prevValue: null,
|
||||||
|
_timer: null,
|
||||||
|
|
||||||
attributeBindings: [
|
attributeBindings: [
|
||||||
"autocorrect",
|
"autocorrect",
|
||||||
"autocapitalize",
|
"autocapitalize",
|
||||||
@ -11,6 +17,28 @@ export default TextField.extend({
|
|||||||
"dir"
|
"dir"
|
||||||
],
|
],
|
||||||
|
|
||||||
|
didReceiveAttrs() {
|
||||||
|
this._super(...arguments);
|
||||||
|
this._prevValue = this.value;
|
||||||
|
},
|
||||||
|
|
||||||
|
didUpdateAttrs() {
|
||||||
|
this._super(...arguments);
|
||||||
|
if (this._prevValue !== this.value) {
|
||||||
|
if (this.onChangeImmediate) {
|
||||||
|
next(() => this.onChangeImmediate(this.value));
|
||||||
|
}
|
||||||
|
if (this.onChange) {
|
||||||
|
cancel(this._timer);
|
||||||
|
this._timer = debounce(this, this._debouncedChange, DEBOUNCE_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_debouncedChange() {
|
||||||
|
next(() => this.onChange(this.value));
|
||||||
|
},
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
dir() {
|
dir() {
|
||||||
if (this.siteSettings.support_mixed_text_direction) {
|
if (this.siteSettings.support_mixed_text_direction) {
|
||||||
@ -23,6 +51,11 @@ export default TextField.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
willDestroyElement() {
|
||||||
|
this._super(...arguments);
|
||||||
|
cancel(this._timer);
|
||||||
|
},
|
||||||
|
|
||||||
keyUp(event) {
|
keyUp(event) {
|
||||||
this._super(event);
|
this._super(event);
|
||||||
|
|
||||||
|
@ -44,3 +44,43 @@ componentTest("sets the dir attribute to ltr for English text", {
|
|||||||
assert.equal(find("input").attr("dir"), "ltr");
|
assert.equal(find("input").attr("dir"), "ltr");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
componentTest("supports onChange", {
|
||||||
|
template: `{{text-field class="tf-test" value=value onChange=changed}}`,
|
||||||
|
beforeEach() {
|
||||||
|
this.called = false;
|
||||||
|
this.newValue = null;
|
||||||
|
this.set("value", "hello");
|
||||||
|
this.set("changed", v => {
|
||||||
|
this.newValue = v;
|
||||||
|
this.called = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async test(assert) {
|
||||||
|
await fillIn(".tf-test", "hello");
|
||||||
|
assert.ok(!this.called);
|
||||||
|
await fillIn(".tf-test", "new text");
|
||||||
|
assert.ok(this.called);
|
||||||
|
assert.equal(this.newValue, "new text");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
componentTest("supports onChangeImmediate", {
|
||||||
|
template: `{{text-field class="tf-test" value=value onChangeImmediate=changed}}`,
|
||||||
|
beforeEach() {
|
||||||
|
this.called = false;
|
||||||
|
this.newValue = null;
|
||||||
|
this.set("value", "old");
|
||||||
|
this.set("changed", v => {
|
||||||
|
this.newValue = v;
|
||||||
|
this.called = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async test(assert) {
|
||||||
|
await fillIn(".tf-test", "old");
|
||||||
|
assert.ok(!this.called);
|
||||||
|
await fillIn(".tf-test", "no longer old");
|
||||||
|
assert.ok(this.called);
|
||||||
|
assert.equal(this.newValue, "no longer old");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Reference in New Issue
Block a user