我在 Nuxt 3 应用程序中使用 VueMultiselect。我在 Nuxt Headless UI Transition Dialog 模式中使用它。当我打开模式时,默认情况下会打开多选。
我有 2 个,其中一个始终开放。如果我只保留一个,那么它是打开的,但如果有 2 个,那么第一个是打开的。
组件/MultiSelect.vue:
<template>
<label class="w-1/6 font-semibold text-base mb-1">{{ label }}</label>
<div class="flex items-center dark:text-white">
<VueMultiselect
v-model="modelValue"
:label="label"
:placeholder="label"
:options="options.map((i) => i.value)"
:custom-label="(opt) => options.find((x) => x.value == opt).text"
:searchable="true"
:close-on-select="false"
:allow-empty="false"
:multiple="true"
:preselect-first="false"
:open-direction="'above'"
:prevent-autofocus="true"
>
</VueMultiselect>
</div>
</template>
<script setup>
import VueMultiselect from "vue-multiselect";
const props = defineProps({
label: {
type: String,
required: false,
},
modelValue: {
type: Array,
required: false,
},
options: {
type: Array,
required: true,
},
});
const emits = defineEmits(["update:modelValue"]);
const modelValue = ref(props.modelValue);
// Emit the updated modelValue when the selectedOption changes
const updateModelValue = () => {
emits("update:modelValue", modelValue.value);
};
// Emit the updated modelValue when the selectedOption changes
watchEffect(() => {
updateModelValue();
});
</script>
<style src="vue-multiselect/dist/vue-multiselect.css"></style>
以下是我对Dialog组件/MyDialog.vue的使用:
<template>
<div class="flex-col items-center">
<div class="mb-2">
<button
type="button"
@click="openModal($event)"
title="$t('pages.modal.sensor-title')"
class="text-cyan-700 border-cyan-700 focus:ring-cyan-300 hover:bg-cyan-800 dark:hover:bg-cyan-600 dark:focus:ring-cyan-800 dark:border-cyan-500 dark:text-cyan-500 block rounded-full hover:text-white border focus:ring-4 focus:outline-none font-medium text-sm px-5 py-2.5 text-center mx-auto dark:hover:text-white"
>
Open
</button>
</div>
</div>
<TransitionRoot appear :show="showModal" as="template">
<Dialog as="div" @close="closeModal" class="relative z-10">
<TransitionChild
as="template"
enter="duration-300 ease-out"
enter-from="opacity-0"
enter-to="opacity-100"
leave="duration-200 ease-in"
leave-from="opacity-100"
leave-to="opacity-0"
>
<div class="fixed inset-0 bg-black bg-opacity-25" />
</TransitionChild>
<div
class="fixed h-fit inset-0 overflow-y-auto flex items-center justify-center"
>
<div
class="fixed inset-0 overflow-y-auto flex items-center justify-center"
>
<TransitionChild
as="template"
enter="duration-300 ease-out"
enter-from="opacity-0 scale-95"
enter-to="opacity-100 scale-100"
leave="duration-200 ease-in"
leave-from="opacity-100 scale-100"
leave-to="opacity-0 scale-95"
>
<DialogPanel
class="flex-grow w-full h-fit transform overflow-visible rounded-2xl bg-gray-200 dark:bg-slate-800 p-6 text-left align-middle shadow-xl transition-all max-w-[70vw] sm:max-w-[70vw] md:max-w-[70vw] lg:max-w-[70vw] xl:max-w-[70vw] 2xl:max-w-[70vw]"
>
<form @submit="onSubmit($event)">
<div class="flex items-center mt-10">
<div class="w-2/5">
<MultiSelect
:label="'Option1'"
v-model="selectedOption1"
:options="options1"
/>
</div>
<div class="w-2/5 ml-5">
<MultiSelect
:label="'Option 2'"
v-model="selectionOption2"
:options="options2"
/>
</div>
</div>
<!-- Submit/Cancel button for the modal -->
<button
type="button"
class="text-red-700 border-red-700 focus:ring-red-300 hover:bg-red-700 dark:hover:bg-red-500 dark:focus:ring-red-800 dark:border-red-500 dark:text-red-500 block rounded-full hover:text-white border focus:ring-4 focus:outline-none font-medium text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:hover:text-white"
@click="closeModal"
>
Submit
</button>
</form>
</DialogPanel>
</TransitionChild>
</div>
</div>
</Dialog>
</TransitionRoot>
</template>
<script setup>
import { ref, defineProps, onBeforeMount } from "vue";
import {
TransitionRoot,
TransitionChild,
Dialog,
DialogPanel,
DialogTitle,
Switch,
} from "@headlessui/vue";
//Import static values for dropdowns
import {
options1,
options2
} from "~/public/Static/DefaultValues";
const showModal = ref(false);
const selectionOption1 = ref([]);
const selectionOption2 = ref([]);
// Open the modal on click of the button
const openModal = () => {
showModal.value = true;
};
// Close the modal on click of the button
const closeModal = () => {
showModal.value = false;
};
</script>
<style>
</style>
页面/View.vue:
<MyDialog />
单击按钮后打开对话框后,我会看到第一个多选下拉列表默认打开。如何解决这个问题?
知道这是因为对话组件将聚焦在第一个可聚焦元素上:
https://headlessui.com/react/dialog#managing-initial-focus
将焦点元素更改为其他元素,如下所示:
<TransitionRoot appear :show="showModal" as="template" initialFocus="{completeButtonRef}">
以及相应的按钮:
<button type="button" @click="closeModal" ref="{completeButtonRef}">Submit</button>