sagalbot / vue-select

Everything you wish the HTML <select> element could do, wrapped up into a lightweight, extensible Vue component.
https://vue-select.org
MIT License
4.63k stars 1.34k forks source link

Vue 3 support #1251

Closed koljada closed 2 years ago

koljada commented 4 years ago

Is your feature request related to a problem? Please describe. It would be great to have a working version for Vue 3.

Describe the solution you'd like New version with Vue 3 support.

Describe alternatives you've considered

Additional context At the moment I can't even install the lib:

vue-select@3.10.7" has incorrect peer dependency "vue@2.x"


Edited by @sagalbot: Vue 3 support is available on the beta release channel.

Please see #1597 as the source of truth for the v4 / Vue 3 compatible release. Thanks! - @sagalbot

npm install vue-select@beta
yarn add vue-select@beta
mk-github-1 commented 3 years ago

There seems to be no update for Vue.js 3 in Vue-Select, so

I decided to use input autocomplate and datalist. The problem is that the header cannot be used in the pull-down menu.

Are there any plans to update Vue-Select?

picks44 commented 2 years ago

Up!

HartleySan commented 2 years ago

Up!

What does that mean?

picks44 commented 2 years ago

Are there any plans to update Vue-Select?

sagalbot commented 2 years ago

Will likely have a beta release today. Tests are passing, docs are building on #1344. Just need to make sure semantic release is configured properly. There are breaking changes that I'd love to get in as part of the v4 release, but I've lagged so hard on this release that I'll likely release as is to support the community.

Fray117 commented 2 years ago

that's great, I was almost losing my hope on vue-select with vue3 support

edited: it seems not compatible with vue-loader 16.1.2

sagalbot commented 2 years ago

@Fray117 can you expand on the vue loader comment?

github-actions[bot] commented 2 years ago

:tada: This issue has been resolved in version 4.0.0-beta.1 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

sagalbot commented 2 years ago

Thanks for the patience folks - I've tagged a beta release.

yarn add vue-select@beta
npm install vue-select@beta

Let me know if you run into any issues! Before tagging a stable release, I will be removing SASS from the component and switching over to CSS properties instead. There may be some other breaking changes still to come, but I'll try to keep them as minimal as possible.

connorshea commented 2 years ago

@sagalbot thanks! I tried it on my Vue 3.1 app as a test and I ran into an issue with my vglist-frontend repo.

I get the following logs in the Chrome console:

log.js?7596:24 [HMR] Waiting for update signal from WDS...
app.js:5324 Uncaught TypeError: Object(...) is not a function
    at Module.eval (vue-select.js?4a7a:formatted:281)
    at o (vue-select.js?4a7a:formatted:4)
    at eval (vue-select.js?4a7a:formatted:61)
    at eval (vue-select.js?4a7a:formatted:64)
    at eval (vue-select.js?4a7a:formatted:2)
    at eval (vue-select.js?4a7a:formatted:2)
    at Object../node_modules/vue-select/dist/vue-select.js (chunk-vendors.js:2493)
    at __webpack_require__ (app.js:5321)
    at fn (app.js:5587)
    at eval (cjs.js??clonedRuleSet-40.use[0]!./node_modules/babel-loader/lib/index.js!./node_modules/ts-loader/index.js??clonedRuleSet-40.use[2]!./node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[1]!./src/components/fields/SingleSelect.vue?vue&type=script&lang=ts:5)

If it helps, you can see the commit where I upgraded (from my fork) to the beta version here.

You can also pull down that repo and try to run it locally on my branch with the upgraded package, if that helps with debugging, like so (make sure you're on Node 16):

It won't work fully without the backend part, but that shouldn't be necessary to see the issue anyway. It should load the initial page with a navbar and "Authenticate" button, and with the vue-select beta it doesn't get that far.

You can also see the error in my CI logs: https://github.com/connorshea/vglist-frontend/runs/3946587562

connorshea commented 2 years ago

@sagalbot looks like it works if I upgrade to Vue 3.2.20 (I also upgraded to the latest versions of vue-router and vuex, but I'm assuming the main Vue package was what mattered). So I guess you either need to fix 3.1.x support or just require >= 3.2.x.

bitrunsolutions commented 2 years ago

This worked for me as well. Thanks @sagalbot

npm install vue-select@beta

package.json
...
  "dependencies": {
     ...
    "jquery": "^3.6.0",
    "jquery-ui-bundle": "^1.12.1-migrate",
    "vue": "^3.2.20",
    "vue-chartjs": "^3.5.1",
    "vue-property-decorator": "^8.0.0",
    "vue-router": "^4.0.12",
    "vue-select": "^4.0.0-beta.1",
    "vuex": "^4.0.2"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~5.0.0-beta.6",
    "@vue/cli-plugin-eslint": "~5.0.0-beta.6",
    "@vue/cli-service": "~5.0.0-beta.6",
    "@vue/compiler-sfc": "^3.2.20",
    "webpack-bundle-tracker": "^0.4.3",
    ...
  },

main.js
import "../node_modules/vue-select/dist/vue-select.css";

insights.vue
<template>
    <li>
        <v-select v-model="bookTypes" :options="['Promos', 'Adverts', 'Others']"></v-select>
    </li>
</template>

<script>
import vSelect from "vue-select";

export default {
  components: {
    vSelect
  },
  data: function() {
    return {
      bookTypes: "Promos",
      ...
</script>
EthanZeigler commented 2 years ago

@sagalbot I'm noticing an issue with https://vue-select.org/guide/values.html#getting-and-setting .It seems the @input event isn't being emitted. Take a look at this.

image

image

console.log never runs.

Update: the value prop also seems to not work. https://vue-select.org/api/props.html#value

whalesalad commented 2 years ago
  1. Use :modelValue instead of :value
  2. Use the event @option:selected in lieu of @input

Here is my current approach that is working:

<v-select
  label="name"
  name="job_type"
  :options="visibleJobTypes"
  :reduce="jobType => jobType.slug"
  :modelValue="selectedJobType"
  :clearable="false"
  @option:selected="optionSelected"
></v-select>
JakeAtTurner commented 2 years ago

Here is a fork with my changes for Vue 3.x support

https://github.com/JakeAtTurner/vue-select/tree/vue3.0-built

bci24 commented 2 years ago

I have installed in vue 3 and I get some errors when selecting or removing an element

`

`

The users object is

const users = ref([ {id: 1, name: 'User 1'}, {id: 2, name: 'User 2'} ])

The error is:

Uncaugh TypeError: Invalid attempt to spread non-iterable instance

Any idea why ?

Finrod927 commented 2 years ago

I have installed in vue 3 and I get some errors when selecting or removing an element

<v-select multiple :options="users" v-model="selectedUsers" :reduce="(user) => user.id" label="name"></v-select>

The users object is

const users = ref([ {id: 1, name: 'User 1'}, {id: 2, name: 'User 2'} ])

The error is:

Uncaugh TypeError: Invalid attempt to spread non-iterable instance

Any idea why ?

I already created an issue for this error: https://github.com/sagalbot/vue-select/issues/1532 There is an MR waiting to be merge to fix it.

Kalifr commented 2 years ago

Here is a fork with my changes for Vue 3.x support

https://github.com/JakeAtTurner/vue-select/tree/vue3.0-built

@JakeAtTurner how can I install your fork?

JakeAtTurner commented 2 years ago

Hey @Kalifr I do not think that the entire project is completely working with Vue 3.X compatibility, but it builds. I have not had time to look into the matter, and it is not something that is necessary for me at the moment. But to use the code you can add it in your npm package and install it using npm install --save JakeAtTurner/vue-select#vue3.0-built

mathiash98 commented 2 years ago

@Kalifr use the beta channel for vue-select "vue-select": "^4.0.0-beta.1", works fine for me. Be sure to upgrade to vue: 3.2.x

btw, for anyone overriding default components =>

Barrandov commented 2 years ago

How do you connect it via CDN? I am trying to make it work, but it raises the problem. https://codepen.io/BarrandovPan/pen/wvrdPJy

kris-sum commented 2 years ago
2. Use the event `@option:selected` in lieu of `@input`

Instead of @input use the event @update:model-value , option:selected only fires when selecting from the dropdown, and doesn't give a null value on clear etc.

amchconsult commented 2 years ago

Looks like CDN way is not working. Error:

Uncaught TypeError: Cannot read properties of undefined (reading 'createTextVNode')
    at Module.<anonymous> (index.js:4)
    at o (index.js:4)
    at index.js:4
    at index.js:4
    at index.js:4
    at index.js:4

using app.component("v-select", VueSelect);

Does someone found a fix for it?

thank you

luisfuertes commented 2 years ago

@connorshea have you been able to solve it?

Uncaught TypeError: Object(...) is not a function
sagalbot commented 2 years ago

@luisfuertes can you provide more details about that error? When does it occur?

mathiash98 commented 2 years ago

@luisfuertes can you provide more details about that error? When does it occur?

Pretty sure this error is due to not having upgrade vue to 3.2.x

amchconsult commented 2 years ago

My testing code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>VUE 3 TEST vue-select</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <!-- <link href="public/assets/vue-select-4.0.0-beta/dist/vue-select.css" rel="stylesheet"> -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vue-select@4.0.0-beta.2/dist/vue-select.css">
</head>
<body>

<style>

</style>

<div id="app">
    <div class="container mt-4">

        <v-select :options="options" v-model="result"></v-select>

    </div>
</div>

<!-- <script src="public/assets/vue3/dist/vue.global.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.26/dist/vue.global.js"></script>
<!-- <script src="public/assets/vue-select-4.0.0-beta/dist/vue-select.js"></script> -->
<!-- <script src="https://cdn.jsdelivr.net/npm/vue-select@4.0.0-beta.2/dist/vue-select.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/vue-select@4.0.0-beta.2/dist/vue-select.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>

<script>
    var vm = Vue.createApp({
        components: {
            'v-select': VueSelect
        },
        data(){
            return {
                options: [
                    'foo',
                    'bar',
                    'baz'
                ],
                result:null,
            }
        },
    })
    .mount('#app')
</script>

</body>
</html>

Thank you

luisfuertes commented 2 years ago

I have "vue": "^3.0.0", I will try to upload the version and I will tell you

bci24 commented 2 years ago

I want to use vue-select as input with autocomplete. I have set a simple sandbox...

https://codesandbox.io/s/frosty-architecture-64qn7?file=/src/App.vue

I have list of countries and if the country is not in the list it will add it.

The problem is when selecting for ex: "Canada" and click again on input ... it will clear the selected item and open the dropdown (which is the default behavior)

I want to be able to edit the selected value (for example "Canda") to change CA or something else ... to work like an standard input text... when click on input to not clear the selected item.

It is possible to make this?

sagalbot commented 2 years ago

@bci24 use taggable https://vue-select.org/guide/values.html#tagging

luisfuertes commented 2 years ago

Hi, with vue version updated all work fine, but i have a problem.

I am reading this section of doc https://vue-select.org/guide/values.html#getting-and-setting

This is my code, i use @input="setSelected" and on setup() i return setSelected function. The problem is setSelected never called. What im doing wrong? Thanks in advanced

(extra data, multiple is true)

<template>
  <div v-bind:class="[{ 'container--disabled': disabled, 'container--error': error }, 'container']">
    <label :for="id ? id : null" class="label" v-if="label">{{ label }}</label>
    <div class="input-container">
      <VueSelect
        class="input-vue-select"
        :id="id"
        :disabled="disabled"
        :options="options"
        :label="labelKey"
        :reduce="v => v[valueKey]"
        @input="setSelected"
        @focus="$emit('on-focus')"
        @blur="$emit('on-blur')"
        :placeholder="placeholder"
        :tabindex="tabindex"
        :multiple="multiple"
      >
      </VueSelect>
      <WarningIcon v-if="error" variant="error" containerClass="warning-icon" />
    </div>
    <span class="info" v-if="info">{{ info }}</span>
    <span class="info error" v-if="error">{{ error }}</span>
  </div>
</template>

<script>
import WarningIcon from '@/assets/icons/warning.vue'
import VueSelect from 'vue-select'
import 'vue-select/dist/vue-select.css'

export default {
  name: 'InputSelect',
  components: {
    WarningIcon,
    VueSelect,
  },
  emits: ['on-change', 'on-blur', 'on-focus'],
  setup(props, { emit }) {
    const setSelected = values => {
      console.log({ values })
      emit('on-change', value)
    }
    return { setSelected }
  },
}
</script>
luisfuertes commented 2 years ago

If i use v-model="selected" and selected is a child component data ref (selected) all works fine, load initial value and set the selected value.

But if use v-model="value" or :value="value" and value come from parent props, it isnt work. Dont load the current value of value and dont call to @input function

Example case 1 (works)

<template>
  <div v-bind:class="[{ 'container--disabled': disabled, 'container--error': error }, 'container']">
    <label :for="id ? id : null" class="label" v-if="label">{{ label }}</label>
    <div class="input-container">
      <VueSelect
        class="input-vue-select"
        :id="id"
        :disabled="disabled"
        :options="options"
        :label="labelKey"
        :reduce="v => v[valueKey]"
        v-model="selected"
        :placeholder="placeholder"
        :tabindex="tabindex"
        :multiple="multiple"
      >
      </VueSelect>
      <span>{{ value }}</span>
      <WarningIcon v-if="error" variant="error" containerClass="warning-icon" />
    </div>
    <span class="info" v-if="info">{{ info }}</span>
    <span class="info error" v-if="error">{{ error }}</span>
  </div>
</template>

<script>
import WarningIcon from '@/assets/icons/warning.vue'
import VueSelect from 'vue-select'
import { ref } from 'vue'
import 'vue-select/dist/vue-select.css'

export default {
  name: 'InputVueSelect',
  components: {
    WarningIcon,
    VueSelect,
  },
  emits: ['on-change', 'on-blur', 'on-focus'],
  setup(props) {

    const selected = ref(props.value)

    return { selected }
  },
}
</script>

Example case 2 (Not works)


<template>
  <div v-bind:class="[{ 'container--disabled': disabled, 'container--error': error }, 'container']">
    <label :for="id ? id : null" class="label" v-if="label">{{ label }}</label>
    <div class="input-container">
      <VueSelect
        class="input-vue-select"
        :id="id"
        :disabled="disabled"
        :options="options"
        :label="labelKey"
        :reduce="v => v[valueKey]"
        :value="value"
        @input="setSelected"
        :placeholder="placeholder"
        :tabindex="tabindex"
        :multiple="multiple"
      >
      </VueSelect>
      <span>{{ value }}</span>
      <WarningIcon v-if="error" variant="error" containerClass="warning-icon" />
    </div>
    <span class="info" v-if="info">{{ info }}</span>
    <span class="info error" v-if="error">{{ error }}</span>
  </div>
</template>

<script>
import WarningIcon from '@/assets/icons/warning.vue'
import VueSelect from 'vue-select'
import { ref } from 'vue'
import 'vue-select/dist/vue-select.css'

export default {
  name: 'InputVueSelect',
  components: {
    WarningIcon,
    VueSelect,
  },
  emits: ['on-change', 'on-blur', 'on-focus'],
  setup(props, { emit }) {

    const setSelected = values => {
      console.log({ values })
      emit('on-change', values)
    }

    const selected = ref(props.value)

    return { setSelected, selected }
  },
}
</script>
luisfuertes commented 2 years ago

This is my provisional workaround

<template>
  <div v-bind:class="[{ 'container--disabled': disabled, 'container--error': error }, 'container']">
    <label :for="id ? id : null" class="label" v-if="label">{{ label }}</label>
    <div class="input-container">
      <VueSelect
        class="input-vue-select"
        :id="id"
        :disabled="disabled"
        :options="options"
        :label="labelKey"
        :reduce="v => v[valueKey]"
        :placeholder="placeholder"
        :tabindex="tabindex"
        :multiple="multiple"
        v-model="selected"
      >
      </VueSelect>
      <WarningIcon v-if="error" variant="error" containerClass="warning-icon" />
    </div>
    <span class="info" v-if="info">{{ info }}</span>
    <span class="info error" v-if="error">{{ error }}</span>
  </div>
</template>

<script>
import WarningIcon from '@/assets/icons/warning.vue'
import VueSelect from 'vue-select'
import { ref, watch } from 'vue'
import 'vue-select/dist/vue-select.css'

export default {
  name: 'InputVueSelect',
  components: {
    WarningIcon,
    VueSelect,
  },
  emits: ['on-change', 'on-blur', 'on-focus'],
  setup(props, { emit }) {
    const selected = ref(props.value)
    watch(selected, newSelected => emit('on-change', newSelected))
    return { selected }
  },
}
</script>

And on parent

               <InputVueSelect
                    id="calendars"
                    :options="calendars"
                    valueKey="uuid"
                    labelKey="name"
                    class="calendar-select"
                    :placeholder="t('calendar.calendarsInputPlaceholder')"
                    :selectedValue="values.calendars"
                    :multiple="true"
                    @on-change="v => (values.calendars = v)"
                    :value="values.calendars"
                    :error="errors.calendars"
                  />
bartenra commented 2 years ago

For me the input event is not popping up as well.


<template>
  <div>
    <v-select
      :options="['Canada', 'United States']"
      @input="log($event)"
      v-model="val"
    ></v-select>
    {{ val }}
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const val = ref('');
const log = (e) => console.log(e);
</script>
raducretu commented 2 years ago

Looks like CDN way is not working. Error:

Uncaught TypeError: Cannot read properties of undefined (reading 'createTextVNode')
    at Module.<anonymous> (index.js:4)
    at o (index.js:4)
    at index.js:4
    at index.js:4
    at index.js:4
    at index.js:4

using app.component("v-select", VueSelect);

Does someone found a fix for it?

thank you

+1

amchconsult commented 2 years ago

You can see my example here. https://github.com/sagalbot/vue-select/issues/1251#issuecomment-1005597589 But it is not working properly.

raducretu commented 2 years ago

You can see my example here. https://github.com/sagalbot/vue-select/issues/1251#issuecomment-1005597589 But it is not working properly.

The code you provided prompts the same error:

Screenshot 2022-01-26 at 14 53 27
sagalbot commented 2 years ago

@luisfuertes sorry about that - the docs need to be versioned and updated. The input event is no longer emitted, use update:modelValue instead. https://v3.vuejs.org/guide/migration/v-model.html#overview

luisfuertes commented 2 years ago

@sagalbot can i use modelValue instead value and update:modelValue instead input props? to receive value from parent component and update it on parent?

sagalbot commented 2 years ago

@luisfuertes yep!

sagalbot commented 2 years ago

I'm going to close this issue in favour of #1597 where it's easier to find consolidated information about the v4 / Vue 3 compatible release, including a checklist for the merge to master, as well as a wishlist of things I hope to accomplish before that happens. Thanks to everyone who's contributed to the conversation!

pierresh commented 2 years ago

Looks like CDN way is not working. Error:

Uncaught TypeError: Cannot read properties of undefined (reading 'createTextVNode')
    at Module.<anonymous> (index.js:4)
    at o (index.js:4)
    at index.js:4
    at index.js:4
    at index.js:4
    at index.js:4

using app.component("v-select", VueSelect); Does someone found a fix for it? thank you

+1

Hello,

I get the same error just by loading the latest vue-select@beta from the CDN <script src="https://unpkg.com/vue-select@beta"></script>

vue-select@beta:1 Uncaught TypeError: Cannot read properties of undefined (reading 'createTextVNode')
    at vue-select@beta:1:2226
    at vue-select@beta:1:22681
    at vue-select@beta:1:22687
    at vue-select@beta:1:228
    at vue-select@beta:1:237

Has anyone found a solution for this?

amchconsult commented 2 years ago

Looks like CDN is not working. I have tried many ways but not luck.

renepardon commented 2 years ago

Hey guys, works good so far but I have a problem with "multiple"/"taggable". Debugging on the Vue Dev console I see the selected values are set but they are not being displayed. If I then select one again, only this one is selected:

How I call my component:

<AnsibleTagsSelect v-model="form.tags"
                   :playbook-default-tags="selectedPlaybook?.tags"
                   :selected="selectedPlaybook?.tags"/>

Custom select component:

```vue ```

Here is the console output:

Bildschirmfoto 2022-06-01 um 07 08 17

So initially no "playbook" is selected. As soon as I select one, the corresponding tags should be set already as selected and they are, but not being displayed as selected. Maybe you can point me to the solution?

I also figured that if I select one, it still appears in the list as selectable.