Как передать массив объектов в автозаполнение vue - PullRequest
0 голосов
/ 26 октября 2018

Фон

Я передаю массив объектов автозаполнению материала, который можно найти здесь .

Когда я выбираю элемент в списке в первый раз, он выдает ошибку, а затем, если я нажимаю на элемент снова, он выбирает его, как и ожидалось.Этот же процесс повторяется каждый раз, когда я нажимаю на элементы в автозаполнении.

Пример ошибки

[Vue warn]: Ошибка в обработчике события для «input»: «TypeError: Невозможно прочитать свойство 'constructor' из undefined"

Пример кода

<template>
<md-autocomplete 
  v-model="customer"
  :md-options="customers" 
  @md-changed="getCustomers" 
  @md-opened="getCustomers"
  @md-selected="getSelected" 
>
</md-autocomplete>
</template>

<script>
data: () => ({
    customers: [],
    customer: "", // I also tried making this a {}
 }),
methods: {
getCustomers(searchTerm) {
  this.customers = new Promise(resolve => {
    if (!searchTerm) {
      resolve(this.GET_CUSTOMERS);
    } else {
      const term = searchTerm.toLowerCase();
      this.customers = this.GET_CUSTOMERS.filter(({ email }) => {
      email.toLowerCase().includes(term);
  });
    resolve(this.customers);
  }
  });
},


getSelected() {
     console.log(this.customer);
   },
}
</script>

Пример данных

GET_CUSOTMERS: [
  { client_id: 1, email: "example@example.com" },
  { client_id: 2, email: "example@example.com" }
];

Вопрос

Что означает эта ошибка и как ее исправить?Я читал, что в ангуляре использовалась ошибка с автозаполнением из материала, которая произошла через эту ошибку несколько лет назад, но я оптимистичен, что это в настоящее время исправимо, а не ошибка для материала vue.

1 Ответ

0 голосов
/ 28 октября 2018

Устранение неполадок при ошибке

Исходя из исходного кода MdAutocomplete * input , searchTerm в вашем случае undefined (отсюда и ошибка доступа к constructor из undefined):

// MdAutocomplete.vue: onInput()
if (this.searchTerm.constructor.toString().match(/function (\w*)/)[1].toLowerCase() !== 'inputevent') {
         ^^^^^^^^^^

И searchTerm обычно равно его value prop :

data () {
  return {
    searchTerm: this.value,
    //...
  }
},
watch: {
  value (val) {
    this.searchTerm = val
  },
  //...
},

... если элемент не выбран :

selectItem (item, $event) {
  const content = $event.target.textContent.trim()
  this.searchTerm = content
  //...
}

Таким образом, когда возникает ошибка, вполне вероятно, что value из MdAutocomplete как-то undefined (из вашего v-model), в результате чего searchTerm также будет undefined. Когда вы выбираете элемент, searchTerm сбрасывается на текстовое содержимое выделения, и ошибки не возникает.

Я не могу воспроизвести эти точные симптомы с помощью фрагмента кода в OP, но, по-видимому, возникают не связанные с этим ошибки: demo . Возможно, в вопросе отсутствуют существенные детали, воспроизводящие проблему.

Использование массива объектов для опций md-autocomplete

  • Обещание md-options (т. Е. this.customers здесь) должно возвращать массив строк, поэтому вам придется преобразовать массив объектов в ожидаемый формат (используя Array.prototype.map):

    this.customers = new Promise(resolve => {
      if (!searchTerm) {
        resolve(GET_CUSTOMERS.map(x => x.email));   // <-- map to `email` property
      } else {
        const term = searchTerm.toLowerCase();
        this.customers = GET_CUSTOMERS.filter(/*...*/).map(x => x.email);   // <-- map to `email` property
        resolve(this.customers);
      }
    }
    
  • Обратный вызов Array.prototype.filter должен возвращать логическое значение для любой фильтрации. Следующая функция стрелки , используемая в качестве обратного вызова, ничего не возвращает:

    GET_CUSTOMERS.filter(({ email }) => {
      email.toLowerCase().includes(term);
    });
    

    Вы можете удалить скобки функции стрелки:

    GET_CUSTOMERS.filter(({ email }) => email.toLowerCase().includes(term));
    

    или используйте оператор return:

    GET_CUSTOMERS.filter(({ email }) => {
      return email.toLowerCase().includes(term);
    });
    

демо (исправлено)

...