mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
script[setup]: interfaces/input-autocomplete-api (#18414)
* script[setup]: interfaces/input-autocomplete-api * Value is required, but allowed null
This commit is contained in:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user