script[setup]: interfaces/input-autocomplete-api (#18414)

* script[setup]: interfaces/input-autocomplete-api

* Value is required, but allowed null
This commit is contained in:
Rijk van Zanten
2023-05-02 17:37:48 -04:00
committed by GitHub
parent a21a28b7cd
commit e61b35ad06

View File

@@ -28,125 +28,89 @@
</div>
</template>
<script lang="ts">
import { useI18n } from 'vue-i18n';
import { defineComponent, ref, PropType } from 'vue';
import axios from 'axios';
import { throttle, get, debounce } from 'lodash';
import { render } from 'micromustache';
<script setup lang="ts">
import api from '@/api';
import axios from 'axios';
import { debounce, get, throttle } from 'lodash';
import { render } from 'micromustache';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
export default defineComponent({
props: {
value: {
type: [String, Number],
default: null,
},
url: {
type: String,
default: null,
},
resultsPath: {
type: String,
default: null,
},
textPath: {
type: String,
default: null,
},
valuePath: {
type: String,
default: null,
},
trigger: {
type: String as PropType<'debounce' | 'throttle'>,
default: 'throttle',
},
rate: {
type: [Number, String],
default: 500,
},
placeholder: {
type: String,
default: null,
},
iconLeft: {
type: String,
default: null,
},
iconRight: {
type: String,
default: null,
},
font: {
type: String as PropType<'sans-serif' | 'serif' | 'monospace'>,
default: 'sans-serif',
},
disabled: {
type: Boolean,
default: false,
},
direction: {
type: String,
default: undefined,
},
},
emits: ['input'],
setup(props, { emit }) {
const { t } = useI18n();
const props = withDefaults(
defineProps<{
value: string | number | null;
url?: string;
resultsPath?: string;
textPath?: string;
valuePath?: string;
trigger?: 'debounce' | 'throttle';
rate?: number | string;
placeholder?: string;
iconLeft?: string;
iconRight?: string;
font?: 'sans-serif' | 'serif' | 'monospace';
disabled?: boolean;
direction?: string;
}>(),
{
trigger: 'throttle',
rate: 500,
font: 'sans-serif',
}
);
const results = ref<Record<string, any>[]>([]);
const emit = defineEmits(['input']);
const fetchResultsRaw = async (value: string | null) => {
if (!value) {
results.value = [];
return;
}
const { t } = useI18n();
const url = render(props.url, { value });
const results = ref<Record<string, any>[]>([]);
try {
const result = await (url.startsWith('/') ? api.get(url) : axios.get(url));
const resultsArray = props.resultsPath ? get(result.data, props.resultsPath) : result.data;
const fetchResultsRaw = async (value: string | null) => {
if (!value) {
results.value = [];
return;
}
if (Array.isArray(resultsArray) === false) {
// eslint-disable-next-line no-console
console.warn(`Expected results type of array, "${typeof resultsArray}" received`);
return;
}
const url = render(props.url, { value });
results.value = resultsArray.map((result: Record<string, unknown>) => {
if (props.textPath && props.valuePath) {
return { text: get(result, props.textPath), value: get(result, props.valuePath) };
} else if (props.valuePath) {
return { value: get(result, props.valuePath) };
} else {
return { value: result };
}
});
} catch (err: any) {
// eslint-disable-next-line no-console
console.warn(err);
}
};
try {
const result = await (url.startsWith('/') ? api.get(url) : axios.get(url));
const resultsArray = props.resultsPath ? get(result.data, props.resultsPath) : result.data;
const fetchResults =
props.trigger === 'debounce'
? debounce(fetchResultsRaw, Number(props.rate))
: throttle(fetchResultsRaw, Number(props.rate));
return { t, results, onInput, emitValue };
function onInput(value: string) {
emitValue(value);
fetchResults(value);
if (Array.isArray(resultsArray) === false) {
// eslint-disable-next-line no-console
console.warn(`Expected results type of array, "${typeof resultsArray}" received`);
return;
}
function emitValue(value: string) {
emit('input', value);
}
},
});
results.value = resultsArray.map((result: Record<string, unknown>) => {
if (props.textPath && props.valuePath) {
return { text: get(result, props.textPath), value: get(result, props.valuePath) };
} else if (props.valuePath) {
return { value: get(result, props.valuePath) };
} else {
return { value: result };
}
});
} catch (err: any) {
// eslint-disable-next-line no-console
console.warn(err);
}
};
const fetchResults =
props.trigger === 'debounce'
? debounce(fetchResultsRaw, Number(props.rate))
: throttle(fetchResultsRaw, Number(props.rate));
function onInput(value: string) {
emitValue(value);
fetchResults(value);
}
function emitValue(value: string) {
emit('input', value);
}
</script>
<style lang="scss" scoped>