Open Uhasith opened 1 week ago
yes similar to this one but in vue https://shadcn-extension.vercel.app/docs/multi-select
Related https://github.com/unovue/shadcn-vue/issues/688
@Uhasith I saw your comment can you create a Stackblitz playground so we could see the problem, thanks
This is the Demo @sadeghbarati
https://stackblitz.com/edit/vitejs-vite-7cpzyx?file=src%2Fcomponents%2FHelloWorld.vue
@Uhasith Check the Stackblitz URL again it's 404: Not Found
@Uhasith Check the Stackblitz URL again it's 404: Not Found
I'm not a paid user. I guess they don't let me share it. This is the Github Repo Link @sadeghbarati
@Uhasith Check the Stackblitz URL again it's 404: Not Found
This should Work @sadeghbarati
[stackblitz.com/edit/vitejs-vite-1qlnyc](https://stackblitz.com/edit/vitejs-vite-1qlnyc)
@Uhasith Check this playground
https://stackblitz.com/edit/github-rxs6gk?file=src%2Fcomponents%2FDialogModal.vue
Your issue was using two Portal components together
@Uhasith Check this playground
https://stackblitz.com/edit/github-rxs6gk?file=src%2Fcomponents%2FDialogModal.vue
Your issue was using two Portal components together
Wow, mate, that was quick! Could you please explain the fix for this issue? Also, could you push the changes to my repo? @sadeghbarati
@Uhasith Check this playground
https://stackblitz.com/edit/github-rxs6gk?file=src%2Fcomponents%2FDialogModal.vue
Your issue was using two Portal components together
I’m new to StackBlitz, so I’m not sure which part you fixed in the codebase, mate. If you don’t mind, could you give me a quick overview? Really appreciate your response ❤️🔥 @sadeghbarati
Use this tool to find out the difference, I changed MultiSelect.vue
and DialogModal.vue
https://it-tools.tech/text-diff
On the left-side pastes your code and right-side paste modified code
Thank you so much! I hope this component will help others who have issues with multiple select as well. ❤️ @sadeghbarati
I created MultiSelect component by modifying the FacetedFilter. It can also fetch the results from the database using an optionsUrl prop
Hope this helps!
MultiSelect.vue
<script setup>
import { ref, onMounted } from "vue";
import { ChevronDown, Check } from "lucide-vue-next";
import { debounce } from "@/lib/utils";
import { Badge } from "@/Components/ui/badge";
import { Button } from "@/Components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
} from "@/Components/ui/command";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/Components/ui/popover";
import axios from "axios";
import Label from "@/Components/ui/label/Label.vue";
const model = defineModel();
const props = defineProps({
title: {
type: String,
required: true,
},
options: {
type: Array,
default: () => [],
},
optionsUrl: {
type: String,
default: null,
},
});
const selectedValues = ref(new Set(model.value));
const optionsList = ref([]);
const q = ref("");
onMounted(() => {
updateOptionList("");
});
const filterFunction = (e) => {
updateOptionList(e.target.value);
};
const updateOptionList = debounce(async (query) => {
if (!props.optionsUrl) return;
q.value = query;
const { data } = await axios.get(props.optionsUrl, {
params: { q: query },
});
optionsList.value = data;
});
const toggleSelection = (optionValue) => {
if (selectedValues.value.has(optionValue)) {
selectedValues.value.delete(optionValue);
model.value = model.value.filter((value) => value !== optionValue);
} else {
selectedValues.value.add(optionValue);
model.value.push(optionValue);
}
};
const clearSelections = () => {
selectedValues.value.clear();
};
</script>
<template>
<div class="flex flex-col gap-2">
<Label>{{ title }}</Label>
<Popover>
<PopoverTrigger as-child>
<Button
variant="outline"
class="h-10 flex justify-between text-muted-foreground font-normal"
>
<span v-if="selectedValues.size < 1">{{ title }}</span>
<template v-if="selectedValues.size > 0">
<Badge
variant="secondary"
class="rounded-sm px-1 font-normal lg:hidden"
>
{{ selectedValues.size }} selected
</Badge>
<div class="hidden space-x-1 lg:flex">
<Badge
v-if="selectedValues.size > 3"
variant="secondary"
class="rounded-sm px-1 font-normal"
>
{{ selectedValues.size }} selected
</Badge>
<template v-else>
<Badge
v-for="option in optionsList.filter(
(option) =>
selectedValues.has(option.value)
)"
:key="option.value"
variant="secondary"
class="rounded-sm px-1 font-normal"
>
{{ option.label }}
</Badge>
</template>
</div>
</template>
<ChevronDown class="ml-2 h-4 w-4" />
</Button>
</PopoverTrigger>
<PopoverContent class="w-[200px] p-0" align="start">
<Command
:should-filter="props.optionsUrl == null"
:filter-function="
props.optionsUrl
? null
: (list, term) =>
list.filter((i) =>
i.label
.toLowerCase()
.includes(term.toLowerCase())
)
"
>
<CommandInput
:placeholder="title"
v-model="q"
@input="filterFunction"
/>
<CommandList>
<CommandEmpty>
{{
optionsUrl && q == ""
? "Start Typing to search"
: "No results found."
}}
</CommandEmpty>
<CommandGroup>
<CommandItem
v-for="option in optionsList"
:key="option.value"
:value="option"
@select="toggleSelection(option.value)"
>
<div
:class="[
'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
selectedValues.has(option.value)
? 'bg-primary text-primary-foreground'
: 'opacity-50 [&_svg]:invisible',
]"
>
<Check class="h-4 w-4" />
</div>
<span>{{ option.label }}</span>
</CommandItem>
</CommandGroup>
<template v-if="selectedValues.size > 0">
<CommandSeparator />
<CommandGroup>
<CommandItem
class="justify-center text-center"
@select="clearSelections"
>
Clear Selection
</CommandItem>
</CommandGroup>
</template>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
</template>
Describe the feature
Currently, the Select component only supports single-item selection. Could we add a variant for selecting multiple items?