vueform / multiselect

Vue 3 multiselect component with single select, multiselect and tagging options (+Tailwind CSS support).
https://vueform.com
MIT License
807 stars 150 forks source link

How to handle Type of @create event #365

Closed mrleblanc101 closed 1 year ago

mrleblanc101 commented 1 year ago

Version

Description

Type '(option: Project) => Promise<{ id: string; name: string; }>' is not assignable to type '(e: { originalEvent: Event; query: string; }) => void'. Types of parameters 'option' and 'e' are incompatible.

Demo

 <Multiselect
      v-model="model.project"
      :options="projects"
      track-by="name"
      label="name"
      value-prop="id"
      :object="true"
      :placeholder="$t('Choisir ou créer...')"
      :classes="classes"
      :appendNewOption="false"
      searchable
      createOption
      @create="addProject"
  />

  async function addProject(option: Project) {
    const project = await addDoc(collection(db, "projects"), {
        name: option.name,
    });
    return {id: project.id, name: option.name};
};
mrleblanc101 commented 1 year ago

Maybe this is very simple to solve, but I'm a TS newbie and I couldn't find how to convert the type or bypass this issue.

Adeiko commented 1 year ago

Maybe this is very simple to solve, but I'm a TS newbie and I couldn't find anything about this.

I do not think it's your problem. I'm also having issues with other events defintions.

Here is my similar case with the @change event.

<script setup lang="ts">
import Multiselect from '@vueform/multiselect'
const modelValue = defineModel<{
  modelValue: string[]
}>()
async function getOptions(){
 //....
}
function testChange(value: string[]) {
  console.log(value)
}
</script>

<template>
 <Multiselect
    v-model="modelValue"
    mode="tags"
    :options="async () => await getOptions()"
    @change="testChange"
  >
</template>

This code works but generates a TS error:

  Types of parameters 'values' and 'e' are incompatible.ts(2322)
(property) 'change': ((e: {originalEvent: Event; value: any; }) => void) | undefined

because @change is defined here like:

$emit(eventName: 'change', e: {originalEvent: Event, value: any}): this;

But really that is not what the function is receiving at all. It receives what is documented "value, select$".

adamberecz commented 1 year ago

Any suggestion what to change it for @Adeiko?

Adeiko commented 1 year ago

Any suggestion what to change it for @Adeiko?

Maybe changing it to:

  $emit(eventName: 'change', value: any, instance: this): this;
  $emit(eventName: 'select', value: any, option: any, instance:this): this;
  $emit(eventName: 'deselect', value: any, option: any, instance:this): this;
  $emit(eventName: 'remove', value: any, option: any, instance:this): this;
  $emit(eventName: 'search-change', query: string, instance: this): this;
  $emit(eventName: 'tag', query: string, instance: this): this;
  $emit(eventName: 'option', query: string, instance: this): this;
  $emit(eventName: 'create', query: string, instance: this): this;
  $emit(eventName: 'paste', e: Event, instance: this): this;
  $emit(eventName: 'keydown', e: Event, instance: this): this;
  $emit(eventName: 'keyup', e: Event, instance: this): this;
  $emit(eventName: 'open'): this;
  $emit(eventName: 'close'): this;
  $emit(eventName: 'clear'): this;
  $emit(eventName: 'max'): this;

I added to the select and deselect the threww variables it sends since according to the code it sends 3 parameters

context.emit('select', finalValue(option), option, $this)
context.emit('deselect', finalValue(option), option, $this)

But in the documentation and in the typescript only 2 are described.

adamberecz commented 1 year ago

Thanks - updated the types with this (also fixed the readme).

mrleblanc101 commented 1 year ago

Thank you, I see the package hasn't been updated since April, when can we expect this change to land ? In a patch relatively soon, or in the next minor/major later ?

adamberecz commented 1 year ago

2.6.3 is just released @mrleblanc101

mrleblanc101 commented 1 year ago

@adamberecz I still get error:

Type '(option: Project) => Promise<{ id: string; name: string; }>' is not assignable to type '(query: string, instance: Multiselect) => void'.

@create should not return void Also, the first argument of @create is not a String when :object="true", it's an object (which should be a generic I suppose)

Can we re-open until the types are really fixed ?

adamberecz commented 1 year ago

Can you try directly the current version from Github? I added some changes.

mrleblanc101 commented 1 year ago

Can you try directly the current version from Github? I added some changes.

Yep this seem to do the job. I'll leave you to close the is ticket when the change is published.