Browse Source

fix: tree-select placeholder error

pull/3053/head
tangjinzhou 4 years ago
parent
commit
e0667855ee
  1. 2
      antdv-demo
  2. 51
      components/_util/BaseInput.tsx
  3. 91
      components/vc-tree-select/src/SearchInput.jsx
  4. 15
      components/vc-tree-select/src/Select.jsx
  5. 35
      components/vc-tree-select/src/Selector/SingleSelector.jsx
  6. 2
      examples/App.vue

2
antdv-demo

@ -1 +1 @@
Subproject commit ab46da93f0bca77a66a25f0ef427fa106d6dff13
Subproject commit 6cb2ff40c46114d4195edcacf82e56b6686ff8a7

51
components/_util/BaseInput.tsx

@ -0,0 +1,51 @@
import { defineComponent, ref, withDirectives } from 'vue';
import antInput from './antInputDirective';
import PropTypes from './vue-types';
const BaseInput = defineComponent({
props: {
value: PropTypes.string.def(''),
},
emits: ['change', 'input'],
setup(_p, { emit }) {
const inputRef = ref(null);
const handleChange = (e: Event) => {
const { composing } = e.target as any;
if ((e as any).isComposing || composing) {
emit('input', e);
} else {
emit('input', e);
emit('change', e);
}
};
return {
inputRef,
focus: () => {
if (inputRef.value) {
inputRef.value.focus();
}
},
blur: () => {
if (inputRef.value) {
inputRef.value.blur();
}
},
handleChange,
};
},
render() {
return withDirectives(
(
<input
{...this.$props}
{...this.$attrs}
onInput={this.handleChange}
onChange={this.handleChange}
ref="inputRef"
/>
) as any,
[[antInput]],
);
},
});
export default BaseInput;

91
components/vc-tree-select/src/SearchInput.jsx

@ -4,8 +4,8 @@
* - multiple: in the selector
* Move the code as a SearchInput for easy management.
*/
import { inject, withDirectives, ref, onMounted, computed, watch } from 'vue';
import antInput from '../../_util/antInputDirective';
import BaseInput from '../../_util/BaseInput';
import { inject, ref, onMounted, computed, watch } from 'vue';
import PropTypes from '../../_util/vue-types';
import { createRef } from './util';
@ -22,38 +22,42 @@ const SearchInput = {
ariaId: PropTypes.string,
isMultiple: PropTypes.looseBool.def(true),
},
setup(props) {
setup(props, { emit }) {
const measureRef = ref();
const inputWidth = ref(0);
const mirrorSearchValue = ref(props.searchValue);
watch(
computed(() => props.searchValue),
() => {
mirrorSearchValue.value = props.searchValue;
},
);
watch(
mirrorSearchValue,
() => {
emit('mirrorSearchValueChange', mirrorSearchValue.value);
},
{ immediate: true },
);
// We measure width and set to the input immediately
onMounted(() => {
if(props.isMultiple) {
if (props.isMultiple) {
watch(
computed(()=>props.searchValue),
mirrorSearchValue,
() => {
inputWidth.value = measureRef.value.scrollWidth;
},
{ flush: 'post', immediate: true },
);
}
});
return {
measureRef,
inputWidth,
vcTreeSelect: inject('vcTreeSelect', {}),
mirrorSearchValue,
};
},
data() {
return {
mirrorSearchValue: this.searchValue,
};
},
watch: {
searchValue(val) {
this.mirrorSearchValue = val;
},
},
created() {
this.inputRef = createRef();
this.prevProps = { ...this.$props };
@ -80,7 +84,6 @@ const SearchInput = {
});
},
methods: {
/**
* Need additional timeout for focus cause parent dom is not ready when didMount trigger
*/
@ -114,7 +117,15 @@ const SearchInput = {
},
render() {
const { searchValue, prefixCls, disabled, renderPlaceholder, open, ariaId, isMultiple } = this.$props;
const {
searchValue,
prefixCls,
disabled,
renderPlaceholder,
open,
ariaId,
isMultiple,
} = this.$props;
const {
vcTreeSelect: { onSearchInputKeyDown },
handleInputChange,
@ -123,27 +134,29 @@ const SearchInput = {
} = this;
return (
<>
<span class={`${prefixCls}-selection-search`} style={isMultiple ? { width: inputWidth + 'px' }:{}}>
{withDirectives(
<input
type="text"
ref={this.inputRef}
onInput={handleInputChange}
onChange={handleInputChange}
onKeydown={onSearchInputKeyDown}
value={searchValue}
disabled={disabled}
class={`${prefixCls}-selection-search-input`}
aria-label="filter select"
aria-autocomplete="list"
aria-controls={open ? ariaId : undefined}
aria-multiline="false"
/>,
[[antInput]],
)}
{isMultiple ? <span ref="measureRef" class={`${prefixCls}-selection-search-mirror`} aria-hidden>
{mirrorSearchValue}&nbsp;
</span> : null}
<span
class={`${prefixCls}-selection-search`}
style={isMultiple ? { width: inputWidth + 'px' } : {}}
>
<BaseInput
type="text"
ref={this.inputRef}
onInput={handleInputChange}
onChange={handleInputChange}
onKeydown={onSearchInputKeyDown}
value={searchValue}
disabled={disabled}
class={`${prefixCls}-selection-search-input`}
aria-label="filter select"
aria-autocomplete="list"
aria-controls={open ? ariaId : undefined}
aria-multiline="false"
/>
{isMultiple ? (
<span ref="measureRef" class={`${prefixCls}-selection-search-mirror`} aria-hidden>
{mirrorSearchValue}&nbsp;
</span>
) : null}
</span>
{renderPlaceholder && !mirrorSearchValue ? renderPlaceholder() : null}
</>

15
components/vc-tree-select/src/Select.jsx

@ -216,13 +216,19 @@ const Select = defineComponent({
this.setState(state);
this.needSyncKeys = {};
},
'$data._valueList'() {
_valueList() {
this.$nextTick(() => {
this.forcePopupAlign();
});
},
'$data._open'(open) {
_open(open) {
this.$nextTick(() => {
if (!open && !this.isSearchValueControlled()) {
this.setState({ _searchValue: '' });
}
if (open && !this.$data._searchValue) {
this.setState({ _filteredTreeNodes: null });
}
const { prefixCls } = this.$props;
const { _selectorValueList: selectorValueList, _valueEntities: valueEntities } = this.$data;
const isMultiple = this.isMultiple();
@ -489,7 +495,6 @@ const Select = defineComponent({
newState._valueEntities || prevState._valueEntities,
);
});
return newState;
},
// ==================== Selector ====================
@ -637,7 +642,6 @@ const Select = defineComponent({
disabled,
inputValue,
treeNodeLabelProp,
multiple,
treeCheckable,
treeCheckStrictly,
autoClearSearchValue,
@ -697,7 +701,7 @@ const Select = defineComponent({
// Clean up `searchValue` when this prop is set
if (autoClearSearchValue || inputValue === null) {
// Clean state `searchValue` if uncontrolled
if (!this.isSearchValueControlled() && (multiple || treeCheckable)) {
if (!this.isSearchValueControlled()) {
this.setUncontrolledState({
_searchValue: '',
_filteredTreeNodes: null,
@ -848,7 +852,6 @@ const Select = defineComponent({
if (isSet) {
// Do the search logic
const upperSearchValue = String(value).toUpperCase();
let filterTreeNodeFn = filterTreeNode;
if (filterTreeNode === false) {
filterTreeNodeFn = () => true;

35
components/vc-tree-select/src/Selector/SingleSelector.jsx

@ -13,6 +13,16 @@ const SingleSelector = {
this.selectorRef = createRef();
this.inputRef = createRef();
},
data() {
return {
mirrorSearchValue: this.searchValue,
};
},
watch: {
searchValue(val) {
this.mirrorSearchValue = val;
},
},
methods: {
onPlaceholderClick() {
this.inputRef.current.focus();
@ -24,19 +34,13 @@ const SingleSelector = {
this.selectorRef.current.blur();
},
_renderPlaceholder() {
const {
prefixCls,
placeholder,
searchPlaceholder,
searchValue,
selectorValueList,
} = this.$props;
const { prefixCls, placeholder, searchPlaceholder, selectorValueList } = this.$props;
const currentPlaceholder = placeholder || searchPlaceholder;
if (!currentPlaceholder) return null;
const hidden = searchValue || selectorValueList.length;
const hidden = this.mirrorSearchValue || selectorValueList.length;
// [Legacy] Not remove the placeholder
return (
@ -51,12 +55,19 @@ const SingleSelector = {
</span>
);
},
onMirrorSearchValueChange(value) {
this.mirrorSearchValue = value;
},
renderSelection() {
const { selectorValueList, prefixCls } = this.$props;
const selectedValueNodes = [];
if (selectorValueList.length) {
if (selectorValueList.length && !this.mirrorSearchValue) {
const { label, value } = selectorValueList[0];
selectedValueNodes.push(<span key="value" title={toTitle(label)} class={`${prefixCls}-selection-item`}>{label || value}</span>);
selectedValueNodes.push(
<span key="value" title={toTitle(label)} class={`${prefixCls}-selection-item`}>
{label || value}
</span>,
);
}
selectedValueNodes.push(
<SearchInput
@ -64,7 +75,9 @@ const SingleSelector = {
{...this.$attrs}
ref={this.inputRef}
isMultiple={false}
/>);
onMirrorSearchValueChange={this.onMirrorSearchValueChange}
/>,
);
return selectedValueNodes;
},
},

2
examples/App.vue

@ -5,7 +5,7 @@
</template>
<script>
import { defineComponent } from 'vue';
import demo from '../antdv-demo/docs/select/demo';
import demo from '../antdv-demo/docs/tree-select/demo';
// import Affix from '../components/affix';
export default defineComponent({
components: {

Loading…
Cancel
Save