javascriptvue.jsvuejs3antdantdv

How to create custom dropdown with user input using antdv (Ant Design Vue | Vue 3)?


I'm attempting to create a custom dropdown using antdv, but the example shown on the docs(https://www.antdv.com/components/select/#Custom-dropdown), doesn't really show me how to add it using user input.

I've created an example here: https://codesandbox.io/s/custom-dropdown-ant-design-vue-3-2-14-forked-3zm0i7?file=/src/demo.vue) but getting stuck trying to input a value. If I use the @mousedown="e => e.preventDefault()" in the div, then I can't access the a-input. If I try to do without it, then the a-input disappears before I can type anything. In case you don't want to click the link, here's the code:


<template>
  <a-select
    v-model:value="value"
    style="width: 120px"
    :options="items.map((item) => ({ value: item }))"
  >
    <template #dropdownRender="{ menuNode: menu }">
      <v-nodes :vnodes="menu" />
      <a-divider style="margin: 4px 0" />
      <!-- <div
        style="padding: 4px 8px;"
        @mousedown="e => e.preventDefault()"
      > -->
      <a-input
        placeholder="add name"
        @mousedown="(e) => e.preventDefault()"
        @change="addItem"
      />
      <!-- </div> -->
    </template>
  </a-select>
</template>

<script>
import { defineComponent, ref } from "vue";

let index = 0;
export default defineComponent({
  components: {
    VNodes: (_, { attrs }) => {
      return attrs.vnodes;
    },
  },
  setup() {
    const items = ref(["jack", "lucy"]);
    const value = ref("lucy");

    const addItem = (name) => {
      console.log("addItem");
      items.value.push(name);
    };
    return {
      items,
      value,
      addItem,
    };
  },
});
</script>

Solution

  • You can take control over the opening/closing of the select by adding the prop :open. You will need to recreate the standard behavior, i.e. @click: open=true, @change open=false, but then it will by default not close when you click your a-input

    I would also suggest only calling addItem on @keypress.enter instead of @change, otherwise it'll call addItem for every keypress.

    updated sandbox

    <a-select
      v-model:value="value"
      style="width: 120px"
      :options="items.map((item) => ({ value: item }))"
      :open="open"
      @click="open = true"
      @change="open = false"
    >
      <template #dropdownRender="{ menuNode: menu }">
        <v-nodes :vnodes="menu" />
        <a-divider style="margin: 4px 0" />
        <a-input
          v-model:value="inputVal"
          placeholder="add name"
          @keypress.enter="addItem()"
        />
      </template>
    </a-select>
    
    setup() {
      const items = ref(["jack", "lucy"]);
      const value = ref("lucy");
      const inputVal = ref("");
      const open = ref(false);
    
      const addItem = () => {
        items.value.push(inputVal.value);
        inputVal.value = "";
      };
      return {
        items,
        value,
        addItem,
        inputVal,
        open,
      };
    }