Quasar QSelect 在执行 AJAX 调用时未打开

Quasar QSelect is not opening when performing AJAX call

我一直在尝试使用 Quasar's select 创建一个简单的 auto complete,但我不确定这是一个错误还是我做错了什么。

问题

每当我单击 QSelect 组件时,它都不会显示可供我选择选项的下拉菜单。

video of the problem

单击 QSelect 组件后,我立即请求获取包含 50 个标签的列表,然后将 tags 填充到我的 QSelect 但下拉列表没有显示。

代码

import type { PropType } from "vue";
import { defineComponent, h, ref } from "vue";
import type { TagCodec } from "@/services/api/resources/tags/codec";
import { list } from "@/services/api/resources/tags/actions";
import { QSelect } from "quasar";

export const TagAutoComplete = defineComponent({
  name: "TagAutoComplete",
  props: {
    modelValue: { type: Array as PropType<TagCodec[]> },
  },
  emits: ["update:modelValue"],
  setup(props, context) {
    const loading = ref(false);

    const tags = ref<TagCodec[]>([]);

    // eslint-disable-next-line @typescript-eslint/ban-types
    const onFilterTest = (val: string, doneFn: (update: Function) => void) => {
      const parameters = val === "" ? {} : { title: val };

      doneFn(async () => {
        loading.value = true;
        const response = await list(parameters);

        if (val) {
          const needle = val.toLowerCase();
          tags.value = response.data.data.filter(
            (tag) => tag.title.toLowerCase().indexOf(needle) > -1
          );
        } else {
          tags.value = response.data.data;
        }

        loading.value = false;
      });
    };

    const onInput = (values: TagCodec[]) => {
      context.emit("update:modelValue", values);
    };

    return function render() {
      return h(QSelect, {
        modelValue: props.modelValue,
        multiple: true,
        options: tags.value,
        dense: true,
        optionLabel: "title",
        optionValue: "id",
        outlined: true,
        useInput: true,
        useChips: true,
        placeholder: "Start typing to search",
        onFilter: onFilterTest,
        "onUpdate:modelValue": onInput,
        loading: loading.value,
      });
    };
  },
});

我试过的

我已经尝试使用组件可用的几个道具,但似乎没有任何效果。

我的理解是,每当我们想使用 QSelect 创建一个 AJAX 请求时,我们应该使用 QSelect 发出的 onFilter 事件并从那里处理案例.

问题

看来updateFn可能不允许async。将 async 动作提升到 solve the issue

const onFilterTest = async (val, update /* abort */) => {
  const parameters = val === '' ? {} : { title: val };
  loading.value = true;

  const response = await list(parameters);
  let list = response.data.data;
  if (val) {
    const needle = val.toLowerCase();
    list = response.data.data.filter((x) => x.title.toLowerCase()
      .includes(needle));
  }
  update(() => {
    tags.value = list;
    loading.value = false;
  });
};

我通过以下代码和模拟值对其进行了测试。

// import type { PropType } from 'vue';
import { defineComponent, h, ref } from 'vue';
// import type { TagCodec } from "@/services/api/resources/tags/codec";
// import { list } from "@/services/api/resources/tags/actions";
import { QSelect } from 'quasar';

export const TagAutoComplete = defineComponent({
  name: 'TagAutoComplete',
  props: {
    modelValue: { type: [] },
  },
  emits: ['update:modelValue'],

  setup(props, context) {
    const loading = ref(false);

    const tags = ref([]);

    const onFilterTest = async (val, update /* abort */) => {
      // const parameters = val === '' ? {} : { title: val };
      loading.value = true;
      const response = await new Promise((resolve) => {
        setTimeout(() => {
          resolve({
            data: {
              data: [
                {
                  id: 1,
                  title: 'Vue',
                },
                {
                  id: 2,
                  title: 'Vuex',
                },
                {
                  id: 3,
                  title: 'Nuxt',
                },
                {
                  id: 4,
                  title: 'SSR',
                },
              ],
            },
          });
        }, 3000);
      });

      let list = response.data.data;
      if (val) {
        const needle = val.toLowerCase();
        list = response.data.data.filter((x) => x.title.toLowerCase()
          .includes(needle));
      }
      update(() => {
        tags.value = list;
        loading.value = false;
      });
    };

    const onInput = (values) => {
      context.emit('update:modelValue', values);
    };

    return function render() {
      return h(QSelect, {
        modelValue: props.modelValue,
        multiple: true,
        options: tags.value,
        dense: true,
        optionLabel: 'title',
        optionValue: 'id',
        outlined: true,
        useInput: true,
        useChips: true,
        placeholder: 'Start typing to search',
        onFilter: onFilterTest,
        'onUpdate:modelValue': onInput,
        loading: loading.value,
      });
    };
  },
});