/** * Renderless component, used to debounce various types of form inputs */ import { debounceTime, distinctUntilChanged, filter, finalize } from "rxjs/operators"; export default { props: { value: { required: true }, delay: { type: Number, required: false, default: 500 }, }, data() { return { previousEmit: null, incomingValue: null, }; }, methods: { sendUpdate(val) { if (val !== this.previousEmit) { this.$emit("input", val); this.previousEmit = val; } }, }, watch: { incomingValue(val) { if (this.delay === 0) { this.sendUpdate(val); } }, }, beforeMount() { if (this.delay !== 0) { const debounced$ = this.watch$("incomingValue").pipe( debounceTime(this.delay), distinctUntilChanged(), filter((val) => val !== null && val !== this.value), finalize(() => this.sendUpdate(this.incomingValue)), ); this.$subscribeTo(debounced$, (val) => this.sendUpdate(val)); } }, render() { return this.$scopedSlots.default({ value: this.value, input: (e) => { // Vue Bootstrap does not conform to the standard // event object format, so check there first this.incomingValue = e && e.target ? e.target.value : e; }, }); }, };