input.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. export default {
  2. template: `
  3. <q-input
  4. v-bind="$attrs"
  5. v-model="inputValue"
  6. :shadow-text="shadowText"
  7. @keydown.tab="perform_autocomplete"
  8. :list="id + '-datalist'"
  9. >
  10. <template v-for="(_, slot) in $slots" v-slot:[slot]="slotProps">
  11. <slot :name="slot" v-bind="slotProps || {}" />
  12. </template>
  13. </q-input>
  14. <datalist v-if="withDatalist" :id="id + '-datalist'">
  15. <option v-for="option in autocomplete" :value="option"></option>
  16. </datalist>
  17. `,
  18. props: {
  19. id: String,
  20. autocomplete: Array,
  21. value: String,
  22. },
  23. data() {
  24. return {
  25. inputValue: this.value,
  26. };
  27. },
  28. watch: {
  29. value(newValue) {
  30. this.inputValue = newValue;
  31. },
  32. inputValue(newValue) {
  33. this.$emit("update:value", newValue);
  34. },
  35. },
  36. computed: {
  37. shadowText() {
  38. if (!this.inputValue) return "";
  39. const matchingOption = this.autocomplete.find((option) =>
  40. option.toLowerCase().startsWith(this.inputValue.toLowerCase())
  41. );
  42. return matchingOption ? matchingOption.slice(this.inputValue.length) : "";
  43. },
  44. withDatalist() {
  45. const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
  46. return isMobile && this.autocomplete && this.autocomplete.length > 0;
  47. },
  48. },
  49. methods: {
  50. updateValue() {
  51. this.inputValue = this.value;
  52. },
  53. perform_autocomplete(e) {
  54. if (this.shadowText) {
  55. this.inputValue += this.shadowText;
  56. e.preventDefault();
  57. }
  58. },
  59. },
  60. };