ant-design-vue/components/vc-tree-select/src/SearchInput.jsx

161 lines
4.0 KiB
Vue
Raw Normal View History

/**
* Since search box is in different position with different mode.
* - Single: in the popup box
* - multiple: in the selector
* Move the code as a SearchInput for easy management.
*/
2019-01-12 03:33:27 +00:00
import PropTypes from '../../_util/vue-types';
import { createRef } from './util';
const SearchInput = {
name: 'SearchInput',
props: {
open: PropTypes.bool,
searchValue: PropTypes.string,
prefixCls: PropTypes.string,
disabled: PropTypes.bool,
renderPlaceholder: PropTypes.func,
needAlign: PropTypes.bool,
ariaId: PropTypes.string,
},
inject: {
2019-01-28 13:09:13 +00:00
vcTreeSelect: { default: () => ({}) },
},
data() {
return {
mirrorSearchValue: this.searchValue,
};
},
watch: {
searchValue(val) {
this.mirrorSearchValue = val;
},
},
2019-01-12 03:33:27 +00:00
created() {
this.inputRef = createRef();
this.mirrorInputRef = createRef();
this.prevProps = { ...this.$props };
},
2019-01-12 03:33:27 +00:00
mounted() {
this.$nextTick(() => {
2019-01-12 03:33:27 +00:00
const { open, needAlign } = this.$props;
if (needAlign) {
2019-01-12 03:33:27 +00:00
this.alignInputWidth();
}
if (open) {
2019-01-12 03:33:27 +00:00
this.focus(true);
}
2019-01-12 03:33:27 +00:00
});
},
2019-01-12 03:33:27 +00:00
updated() {
const { open, searchValue, needAlign } = this.$props;
const { prevProps } = this;
this.$nextTick(() => {
if (open && prevProps.open !== open) {
2019-01-12 03:33:27 +00:00
this.focus();
}
if (needAlign && searchValue !== prevProps.searchValue) {
2019-01-12 03:33:27 +00:00
this.alignInputWidth();
}
2019-01-12 03:33:27 +00:00
this.prevProps = { ...this.$props };
});
},
methods: {
/**
2019-01-12 03:33:27 +00:00
* `scrollWidth` is not correct in IE, do the workaround.
* ref: https://github.com/react-component/tree-select/issues/65
* clientWidth 0 when mounted in vue. why?
*/
alignInputWidth() {
this.inputRef.current.style.width = `${this.mirrorInputRef.current.clientWidth ||
this.mirrorInputRef.current.offsetWidth}px`;
},
/**
2019-01-12 03:33:27 +00:00
* Need additional timeout for focus cause parent dom is not ready when didMount trigger
*/
focus(isDidMount) {
if (this.inputRef.current) {
if (isDidMount) {
setTimeout(() => {
2019-01-12 03:33:27 +00:00
this.inputRef.current.focus();
}, 0);
} else {
// set it into else, Avoid scrolling when focus
this.inputRef.current.focus();
}
}
},
2019-01-12 03:33:27 +00:00
blur() {
if (this.inputRef.current) {
2019-01-12 03:33:27 +00:00
this.inputRef.current.blur();
}
},
handleInputChange(e) {
const { value, composing } = e.target;
const { searchValue = '' } = this;
if (e.isComposing || composing || searchValue === value) {
this.mirrorSearchValue = value;
return;
}
this.vcTreeSelect.onSearchInputChange(e);
},
},
2019-01-12 03:33:27 +00:00
render() {
const { searchValue, prefixCls, disabled, renderPlaceholder, open, ariaId } = this.$props;
const {
vcTreeSelect: { onSearchInputKeyDown },
handleInputChange,
mirrorSearchValue,
2019-01-12 03:33:27 +00:00
} = this;
return (
<span class={`${prefixCls}-search__field__wrap`}>
<input
2019-01-12 03:33:27 +00:00
type="text"
{...{
directives: [
{
name: 'ant-ref',
value: this.inputRef,
},
2019-11-14 11:19:24 +00:00
{
name: 'ant-input',
},
2019-01-12 03:33:27 +00:00
],
}}
onInput={handleInputChange}
onKeydown={onSearchInputKeyDown}
value={searchValue}
disabled={disabled}
class={`${prefixCls}-search__field`}
2019-01-12 03:33:27 +00:00
aria-label="filter select"
aria-autocomplete="list"
aria-controls={open ? ariaId : undefined}
2019-01-12 03:33:27 +00:00
aria-multiline="false"
/>
<span
2019-01-12 03:33:27 +00:00
{...{
directives: [
{
name: 'ant-ref',
value: this.mirrorInputRef,
},
],
}}
class={`${prefixCls}-search__field__mirror`}
>
{mirrorSearchValue}&nbsp;
</span>
{renderPlaceholder && !mirrorSearchValue ? renderPlaceholder() : null}
</span>
2019-01-12 03:33:27 +00:00
);
},
2019-01-12 03:33:27 +00:00
};
2019-01-12 03:33:27 +00:00
export default SearchInput;