You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Hydro/packages/ui-default/components/autocomplete/index.jsx

81 lines
2.0 KiB
React

import React from 'react';
import ReactDOM from 'react-dom';
import { assign } from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import AutoCompleteFC from './components/AutoComplete';
export default class AutoComplete extends DOMAttachedObject {
static DOMAttachKey = 'ucwAutoCompleteInstance';
constructor($dom, options = {}) {
super($dom);
this.options = {
items: async () => [],
render: () => '',
text: () => null,
multi: false,
...options,
};
this.ref = null;
this.onChange = this.onChange.bind(this);
this.container = document.createElement('div');
this.$dom.addClass('autocomplete-dummy').after(this.container);
// Note: use `setTimeout(fn, 0)` to ensure that code is executed after browser autofill
// also see https://stackoverflow.com/a/779785/13553984
setTimeout(() => this.attach(), 0);
}
clear(clearValue = true) {
if (!this.ref) return;
if (clearValue) this.ref.clear();
else this.ref.closeList();
}
onChange(val) {
this.$dom.val(val);
}
attach() {
const value = this.$dom.val();
ReactDOM.render(
<AutoCompleteFC
ref={(ref) => { this.ref = ref; }}
height="34px"
itemsFn={this.options.items}
renderItem={this.options.render}
itemText={this.options.text}
defaultItems={value}
onChange={this.onChange}
multi={this.options.multi}
freeSolo={this.options.multi}
/>,
this.container,
);
}
open() {
if (!this.ref) return;
this.ref.triggerQuery();
}
close() {
if (!this.ref) return;
this.ref.closeList();
}
detach() {
if (this.detached) return;
super.detach();
ReactDOM.unmountComponentAtNode(this.container);
this.$dom.removeClass('autocomplete-dummy');
this.container.parentNode.removeChild(this.container);
}
focus() {
this.ref.focus();
}
}
assign(AutoComplete, DOMAttachedObject);
window.Hydro.components.autocomplete = AutoComplete;