vueform / multiselect Goto Github PK
View Code? Open in Web Editor NEWVue 3 multiselect component with single select, multiselect and tagging options (+Tailwind CSS support).
Home Page: https://vueform.com
License: MIT License
Vue 3 multiselect component with single select, multiselect and tagging options (+Tailwind CSS support).
Home Page: https://vueform.com
License: MIT License
Added addTagOn
prop in 1.3.3
.
Originally posted by @adamberecz in #37 (comment)
When i'am adding new tags by space, every tag ends with space symbol.
tags:Array[3]
0:"123 "
1:"1235dcdcd "
2:"1232132 "
<template>
<div>
<multiselect2
mode="single"
:value="selectedCountries"
label="entityName"
trackBy="entityName"
@select="select"
:object="true"
:placeholder="placeholder"
open-direction="bottom"
:options="countries"
:searchable="true"
:loading="isLoading"
:internal-search="false"
:clear-on-select="false"
:close-on-select="false"
:filterResults="false"
:options-limit="300"
:limit-text="limitText"
:max-height="200"
@search-change="asyncFind"
>
<template #noResult>
<span>Oops! No elements found.</span>
</template>
</multiselect2>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, nextTick } from "vue";
import _ from "lodash";
import Multiselect from "@vueform/multiselect";
import { useStore } from "../../../../store/modules";
import {
ActionTypes,
AirPortType,
} from "../../../../../src/store/modules/avia/contract";
const MIN_LEN_SEARCH = 2;
export default defineComponent({
name: "SearchAirPort",
props:{
placeholder: String
},
components: {
Multiselect2: Multiselect,
},
setup(props, { emit }) {
// пока так не могу обойти фильтра селекта
type extendAirPort = {
entityId: number;
languageId: number;
entityCode: string;
entityName: string;
complexName: string;
};
type searchCity = Array<extendAirPort>;
const selectedCountries = ref<AirPortType | null>(null);
const countries = ref<searchCity>([]);
const isLoading = ref<boolean>(false);
const store = useStore();
const limitText = (count) => {
return `and ${count} other countries`;
};
const asyncFindFunc = _.debounce(async (query: string) => {
console.log("search");
isLoading.value = true;
const paramsIn = {
searhAirport: query,
};
const res = await store.dispatch(ActionTypes.SEARH_AIRPORT, paramsIn);
if (res) {
countries.value = res.map((item) => {
return {
...item,
complexName: item.entityCode + " " + item.entityName,
};
});
}
isLoading.value = false;
}, 500);
const asyncFind = (query: string) => {
if (query && query.length > MIN_LEN_SEARCH) {
asyncFindFunc(query);
}
};
const select = (selectedOption: null | AirPortType) => {
selectedCountries.value = selectedOption;
let convetData: AirPortType | null = null;
if (selectedOption) {
convetData = {
entityId: selectedOption.entityId,
languageId: selectedOption.languageId,
entityCode: selectedOption.entityCode,
entityName: selectedOption.entityName,
};
}
emit("select-data", convetData);
};
return {
selectedCountries,
countries,
isLoading,
limitText,
asyncFind,
select,
};
},
});
</script>
<style scoped></style>
пришлось пойти на хитрость изобретать extendAirPort что бы все норм было.
но проблема в том что фильтрация не отключается как показано в документации
I had to go to the trick of inventing extendAirPort that everything would be normal.
but the problem is that filtering is not disabled as shown in the documentation
TypeError: Cannot read property 'value' of undefined (Typescript Vue 3)
Hi guys,
I using Laravel and Vue and in some cases i have regular point to point form submission without ajax request.
When i place request to my controller, i can't see selected options in tag mode.
I found some work-around with @ change event to populate some hidden input, but it will be better if vue-multiselect package can handle this case.
my final work-around;
add this somewhere in vue component
<input v-for="id in v-model" type="hidden" name="variable_name[]" :value="id" />
Thanks.
Because the component listen to mousedown
events, right clicks trigger actions just like a normal click.
For example if you right click on the button to delete an item — let’s say to inspect it — the item gets removed.
It would be better to listen to the click event to avoid this unexpected behavior.
Hello together. Happy new year.
When I select a option, modelValue changed but the input stays empty.
Here my code example:
<template>
<div>
<Multiselect
v-model="value"
:options="options"
value-prop="customer"
label="bezeichnung1"
/>
</div>
</template>
<script>
import Multiselect from "@vueform/multiselect";
export default {
components: {
Multiselect,
},
data() {
return {
value: null,
options: [
{ bezeichnung1: "test", customer: "1" },
{ bezeichnung1: "test2", customer: "2" },
{ bezeichnung1: "test3", customer: "3" },
{ bezeichnung1: "test4", customer: "4" },
],
};
},
};
</script>
<style src="@vueform/multiselect/themes/default.css"></style>
When I change "customer" to "value" in template and script, it's working.
This problem is only in "single" mode.
Currently I set :add-tag-on="[]"
and handle tagging carefully by testing every key typed with regex before addition.
Unfortunately I cannot implement features like on enter jump to next input
, on enter do other stuff like add tag manually or display html5 validation message if something is wrong
.
Could you provide option to turn @keydown.prevent.enter
off so developers can handle this feature by themselves?
I think this won't take much time to implement and will make your component much more flexible.
Is there any way to set the limit of selected options or/and created tags?
Please, add types definition for Typescript support.
Is there any way to use the tags mode without opening the select?
I just want to add new strings without the option to select any string from the list.
Tanks
I'm using Nuxt with the composition API and trying to get this plugin to work. When I try to load it, I get the above error:
Cannot use import statement outside a module
Please use our JSFiddle template to reproduce the bug. Issues without working reproduction might be ignored.
Here's a gist of the file. Not doing anything special.
We use html5 validation in our project and consider using the library, but we miss one feature the "required" attribute. Is there any way to get it?
For some reason, when there are more than two elements, it emit an array of undefined.
https://jsfiddle.net/zmcLda64/5/
Is it possible to get the selected values as ['kia', 'mazda'] and not [1, 2] as it is now?
options: ['ford', 'kia', 'mazda'] and mode is tags
Hi,
I'm having some trouble when doing some search in the "tags with async options". When the user do some search, pick an option and do another search that does not contain the first picked option, the component stop working. I'm not sure, but I suspect the problem is that the component try to retrieve some information about the tag in the options list but the option array doesn't have it on the second search.
This issue can be easily reproduced in example number 6 - Tags with async options (https://jsfiddle.net/q6Lnpr7a/).
To reproduce this error:
1 - Search for 'a';
2 - Choose '@Formula' option;
3 - Search for 'b';
Thank you very much.
Hi,
I'm having some trouble when the component is searcheable and the search term contains spaces. When the user types space, the first option of the combo is selected / deselected, making it impossible to search for more than one term. This can be seen in demo number 5 - Autocomplete with async options (https://jsfiddle.net/q6Lnpr7a/). I'm not sure, but I suspect the problem is onKeyup event.
Could you check it, please?
Thank you very much.
This is my code. It works just fine, except when "restaurantId" has initial value, it doesn't pre-select the option.
<restaurant-autocomplete v-model="filters.restaurantId" />
//Int
RestaurantAutocomplete.vue:
<template>
<Multiselect
:delay="500"
:resolveOnLoad="!!$attrs.modelValue"
:options="async (q) => await autocomplete(q)" // [{value: Int, label: String}]
:searchable="true"
:filterResults="false"
:clearOnSearch="true"
:clearOnSelect="false"
placeholder="Restaurant"
:loading="loading"
@select="$emit('update:modelValue', $event)"/>
</template>
Hi,
is there any way to disable "deselect" event in the single mode?
Thanks
https://jsfiddle.net/sunecosuri/3otvkf1p/9/
If you try to enter the initial value while it is being entered and before it is converted, the text will overlap.
Is there any way to fix this?
Hi there folks,
If the title is not already clear I try to explain what I mean and what I am trying to achieve. I am using Vue3 by the way.
I would like to have an event when the user clicks on the nooptions
and noresults
slots - just like the @select
event. At the moment it doesn't work if I add a @click
on the custom template slot as per below example:
<multiselect ...>
<template v-slot:noresults>
<div class="multiselect-option" @click="openModal">
Create New
</div>
</template>
</multiselect>
Am I missing something or at the current stage it should not work until a custom event within the package is added?
Hello, is it possible to add these features?
As mentioned in #33 I would like to be able to prefill tags by only using the v-model
. Currently (v1.3.3) I need to provide :options
with matching tags to prefill the tags input even when setting the new showOptions
/show-options
property to false
.
That's redundant imo.
In using multiselect in tags mode is it possible to pre-populate tags with existing values when showing the control.
See https://jsfiddle.net/57okrzx2/3/ which sets the v-model
value on creation but it isn't reflected on the control
Thanks
I need to programmatically focus the input field. Before, we used a normal <input>
element and were able to simply this.$refs.input.focus()
. This is not possible when using multiselect and I couldn't find anything in the docs or code that would allow it.
My current workaround is this:
const input = this.$refs.input.$el.getElementsByTagName("input")[0]
input && input.focus()
Is there are more elegant way of solving this? Thanks!
I stumbled upon this in my project but could reproduce in the demo with "example #5 - Autocomplete with async options" as well:
Note this issue is not about case-insensitive search! The async backend function could also return "Practical Extraction and Report Language" when searching for "perl". My use case is a search for languages where searching for the language names or codes returns language names, e.g. search "de" will show first list entry "German".
Hi, many thanks for implementing html5 required feature. I think your project is going to be very popular because everybody who uses vue-multiselect
and plans to migrate to vue3 looks for alternatives and your project stands out from the rest.
I'm writing for another feature request. Currently if multiselect is near the bottom of modal , or near the bottom of page it opens to bottom and user has to scroll down to see available options. This is very unpleasant experience, especially if user uses mobile phone. Is there any way to get open direction to top
?
If :object="true" the dropdown doesn't close after selecting an option. This might be intended for mode="multiselect", but it happens also for single select.
Hi!
Using v1.2.5 multiselect in the single mode with searchable: true
When i set placeholder option i see it in html markup in div.multiselect-placeholder
Is there any way to move placeholder into input field (div.multiselect-search > input)?
Thanks.
The cross and arrow when you select a person is a bit confusing to use.
I was retouching it, and I have seen that it is due to the heigth default of the images, but I think that the optimal solution instead of hiding it due to overflow, hide it with a v-if if it detects that there is a selected value the arrow that disappears and becomes the cross and the other way around. regards!
<Multiselect
v-model="value"
mode="tags"
placeholder="Select employees"
trackBy="name"
label="name"
:search="true"
:options="[
{
value: 'judy',
name: 'Judy',
image: 'https://randomuser.me/api/portraits/med/women/1.jpg',
},
{
value: 'jane',
name: 'Jane',
image: 'https://randomuser.me/api/portraits/med/women/2.jpg',
},
{
value: 'john',
name: 'John',
image: 'https://randomuser.me/api/portraits/med/men/1.jpg',
},
{
value: 'joe',
name: 'Joe',
image: 'https://randomuser.me/api/portraits/med/men/2.jpg',
},
]"
<template v-slot:tag="{ option, handleTagRemove, disabled }">
<div class="multiselect-tag is-user">
<img :src="option.image" />
{{ option.name }}
<i
v-if="!disabled"
@click.prevent
@mousedown.prevent.stop="handleTagRemove(option, $event)"
/>
</div>
</template>
<template v-slot:option="{ option }">
<img class="character-option-icon" :src="option.image" />
{{ option.name }}
</template>
When you enable the searchable
option:
.multiselect-options
element catch the focus instead. This shouldn’t happen since this element is hidden.https://codesandbox.io/s/festive-glitter-ujwnh?file=/src/App.vue
I'm using a callback in refreshOptions to update the options for a rendered multi-select. Providing an option via this update that matches the value in modelValue isn't selected automatically, and I cannot select it via the .select() api as there is no promise or similar to respond to.
Is there a work-around or something I'm missing?
this.$refs.input.refreshOptions(
this.getItems().then(() => {
this.$refs.input.select(this.modelValue); // this fails because the multi-select isn't yet up to date with the new options, I probably shouldn't have to do this at all considering the modelValue is already set.
})
);
Unable to scroll through dropdown options whenever multiselect component is inside div element with tabindex value assigned.
I need to use such component inside a modal whose tabindex value is set to "-1" by default. When I try scrolling through dropdown options by clicking anywhere in the scrollbar, the dropdown list is immediately closes, losing focus. Any parent div element with any tabindex value assigned (not empty) causes this behavior. It's important to note that scrolling works by using the keyboard or mouse wheel. I'm able to select items in this dropdown list by clicking them, it's only a scrollbar issue.
Hi,
it seems that if you change options accessing data directly, rendered options are not updated.
What I'm missing?
Here an example: after 3 seconds options inside data are changed (check console) but options in the select are not regenerated.
https://jsfiddle.net/ex3ntia/vLdfetq7/6/
Thank you
Show previously added options when using async options search
I`m using the select for async search options
v-model="cities"
mode="tags"
:searchable="true"
:options="async (query) => {
return await fetchCities(query)
}"
:minChars="1"
:resolveOnLoad="true"
:delay="0"
I set resolveOnLoad="true", but how can I show tags, that asynchronously comes to v-model on form init, in the select field? Is there any way to set something like 'defaultOptions / initialOptions' when I`m "searching" for options and adding them as tags?
For now, we add a tag by 'Enter'. Is there any way to add a tag (via creating) by 'Space'?
E.g. typing 'tagNumber1', pressing 'Space', boom, tag created.
We have typical use case: country select, translated to several locales. Options is array of objects:
const options = [{code: 'au', name: 'Autstralia'}]
If we have selected value au
for example in English locale, our label shows Australia
. But when change locale for example to Russian (ru
), and update options, label will remain the same
I wrote test-case for this to clear our problem:
it('should reactively changes label when options has been changed', () => {
let select = createSelect({
value: 'ru',
label: 'name',
valueProp: 'code',
options: [{ code: 'au', name: 'Australia' }, { code: 'ru', name: 'Russia' }, { code: 'us', name: 'USA' }],
})
select.vm.options = [{ code: 'au', name: 'Австралия' }, { code: 'ru', name: 'Россия' }, { code: 'us', name: 'США' }]
expect(select.find('.multiselect-single-label').element).toBeVisible()
expect(select.find('.multiselect-single-label').html()).toContain('Россия') // <---- Fails here, but shouldn't
})
Hello and Happy new year.
Probably the solution is very easy but I just can't make it work.
My problem is
when i trying to use Multiselect with an array of objects from api.
.get("/strategy/g") .then((response) => { this.strategies = response.data; })
in 'strategies' is stored the data
the output looks like this:
[ { "id": 2, "name": "Test one", "user_id": 1, }, { "id": 1, "name": "Test two ", "user_id": 2 } ]
Now when i try to output this in Multiselect
<Multiselect v-model="form.strategy_id" label="name" valueProp="id" trackBy="name" :searchable="true" :createTag="true" :object="true" :options="strategies" />
i get nothing
I also have tried like this but unfortunately without success
<Multiselect v-model="form.strategy_id" label="label" valueProp="value" trackBy="label" :searchable="true" :createTag="true" :object="true" :options="strategies.map((item) => { return { value: item.id, label: item.name }; })" />
Thanks in advance
Hi,
need to disable a few options of a filteredList and still need them to be listed in the dropdown (like crossed out).
I tried with:
[ { "value": "1", "label": "de-AT", "disabled": false }, { "value": "2", "label": "de-CH", "disabled": false }, { "value": "3, "label": "en-GB", "disabled": false }, { "value": "4", "label": "en-CA", "disabled": false }, { "value": "5", "label": "de-DE", "disabled": true }, { "value": "6", "label": "en-US", "disabled": false } ]
as options, but this doesn't really do anything.
Is there a possibility to achieve this or is your multiselect designed to display only choosable options?
Do you have any plans for adding accessibility features to the component in the near future?
See the simple demo below. It is using 1.3.0
. Select a tag, then click it to remove it. It works. Now change the version to 1.3.2
. Select a tag, then click to remove it. An error is thrown and the tag isn't removed.
https://jsfiddle.net/do30skf2/1/
It seems like the { remove }
option is no longer present or working in v-slot:tag
? In my actual project (setup using Vue CLI), I'm getting the error runtime-core.esm-bundler.js?5c40:217 Uncaught TypeError: remove is not a function
.
What about functionality for grouping options? Like in this module:
https://vue-multiselect.js.org/#sub-option-groups
Hello,
is it intended that there is always a scrollbar at the bottom of the options dropdown?
If not, maybe change:
.multiselect-options{ overflow: scroll }
to:
.multiselect-options{ overflow-y: scroll }
regards,
lux
This is a pretty big deal.. I just noticed this multiselect is completely unresponsive on my Android phone. It's not only my personal project, your own demo shows the same results https://jsfiddle.net/q6Lnpr7a/
Try the Autocomplete demo #5. I haven't tested it on IOS but on Android if you try to type inside the autocomplete box, the text goes on top of the placeholder, and it doesn't actually perform any search! It appears to perform a search when you tap outside the box, but then I think that also causes your text to disappear to it doesn't actually search.
Works perfectly on desktop. Also you can't reproduce this using Desktop Chrome's "device toolbar". Maybe you can reproduce it with GenyMotion/Xcode simulator.. hopefully you have an Android phone available.
Hey!
Thank you very much for this very easy to use and customizable component! 🎉
It works very well so far, except showing initial selected values. In the example below I load a list of users and their associated roles and a list of all roles as well.
The user.role_ids
property is an array with only one value [ 1 ]
, but nothing is displayed in the Multiselect
component.
When selecting one of the options in the Multiselect dropdown, the user.role_ids
changes and the entry is displayed in the components div.
But I can see no difference in the result in user.role_ids
.
Is there something I am missing or using the component the wrong way?
Example:
<template>
<div>
<div v-for="user in state.users" :key="user.id">
{{ user }}
// { "id": 1, "name": "Admin", "email": "....", "created_at": "2017-12-20T09:47:36.000000Z",
// "updated_at": "2021-01-26T14:19:00.000000Z", "role_ids": [ 1 ],
// "roles": [ { "id": 1, "name": "admin", "display_name": "Administrator", "description": "Project Administrator",
// "created_at": "2017-12-20T09:47:35.000000Z", "updated_at": "2017-12-20T09:47:35.000000Z" } ] }
{{ user.role_ids }}
// [ 1 ]
{{ state.roles }}
// [ { "id": 1, "name": "admin", "display_name": "Administrator", "description": "Project Administrator",
// "created_at": "2017-12-20T09:47:35.000000Z", "updated_at": "2017-12-20T09:47:35.000000Z" },
// { "id": 2, "name": "guest", "display_name": "Guest", "description": "Guest User",
// "created_at": "2017-12-20T09:47:35.000000Z", "updated_at": "2017-12-20T09:47:35.000000Z" } ]
<multiselect
v-model="user.role_ids"
:label="'display_name'"
:track-by="'display_name'"
:valueProp="'id'"
:mode="'tags'"
:searchable="true"
:options="state.roles"
:placeholder="t('main.user.add-role-placeholder')">
</multiselect>
</div>
</div>
</template>
<script>
import {
computed,
reactive,
} from 'vue';
export default {
setup() {
const state = reactive({
userList: computed(_ => store.getters.users),
roles: computed(_ => store.getters.roles),
});
return {
state
}
}
</script>
It would be nice to add a way to customize the placeholder template.
Hi,
readMe typo: multipleLabel
should be multiplelabel
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.