Konstantin18ko
@Konstantin18ko
Стоматолог

Почему при поиске вылезает TypeError: Cannot read property 'toString' of null?

Решил взять здесь код для поиска во VueJS 2.0
Однако при поиске выдает ошибку:

vue.min.js:6 TypeError: Cannot read property 'toString' of null
    at Object.values.some.m (home.js:281)
    at Array.some (<anonymous>)
    at sortedTokens_VMP.filter.n (home.js:281)
    at Array.filter (<anonymous>)
    at a.filteredTokens_VMP (home.js:281)
    at Kr.get (vue.min.js:6)
    at Kr.evaluate (vue.min.js:6)
    at a.filteredTokens_VMP (vue.min.js:6)
    at a.eval (eval at Tn (vue.min.js:6), <anonymous>:3:4728)
    at a.t._render (vue.min.js:6)

Как выглядит код:

computed: {
  sortedTokens_VMP() {
    const k = this.sortKey
    return this.tokens_VMP.sort((a, b) => (a[k] < b[k] ? -1 : a[k] > b[k] ? 1 : 0) * [1, -1][+this.reverse])
  },
  filteredTokens_VMP() {
    const s = this.search.toLowerCase()
    return this.sortedTokens_VMP.filter(n => Object.values(n).some(m => m.toString().toLowerCase().includes(s)))
  }
},
methods: {
  sortBy: function (sortKey) {
    this.reverse = (this.sortKey == sortKey) ? !this.reverse : false;
    this.sortKey = sortKey;
  },
},

Чисто поменял переменные.
Сам объект:

number_token:(...)
patient: {last_name: 'test', first_name: 'test'}
place_residence:(...)
profile:(...)
recourse:(...)
result_hospitalization:(...)
short_name_MO:(...)
social_group:(...)
stage:(...)
subject_RF:(...)
treatment_method:(...)
view_appeal:(...)
view_extract:(...)
  • Вопрос задан
  • 161 просмотр
Решения вопроса 1
0xD34F
@0xD34F Куратор тега Vue.js
Какое-то из свойств объекта оказалось null'ом. Почему бы не добавить проверку перед toString'ом - что именно вы собираетесь преобразовывать? Может и не надо перегонять null'ы в строки, может, в этом случае результат поиска сразу отрицательный должен быть. Ну или преобразовывайте в строку как-нибудь иначе, варианты разные есть: ('' + m) или `${m}` или String(m).

А вообще, вы конечно поторопились вот так в лоб использовать первый попавшийся код. Вон, у вас там ещё и вложенные объекты есть, по их свойствам поиск корректно работать не будет (т.к. дефолтное строковое представление объекта - это '[object Object]') - об этом вы подумали? Нет, точно надо проверять, что за значение:

return this.sortedTokens_VMP.filter(n => Object.values(n).some(m => {
  if (m instanceof Object) {
    // проверяем объект, возможно, стоит сделать какую-нибудь рекурсивную функцию под это дело
  } else if (typeof m === 'number') {
    // а вдруг числа надо обрабатывать иначе, чем строки
  } else {
    // какая-то дефолтная проверка значения
  }
}));

UPD. А сортировка, сортировка-то - тоже ведь ерунда получится при работе с null'ами и вложенными свойствами.

Вот как всё будет:

Рекурсивная функция, которая проверяет, есть ли где во вложенных объектах указанная строка:

const includes = (obj, str) => Object
  .values(obj)
  .some(n => n instanceof Object
    ? includes(n, str)
    : `${n}`.toLowerCase().includes(str)
  );

Используем её внутри вычисляемого свойства, представляющего отфильтрованные данные:

filteredTokens_VMP() {
  const s = this.search.toLowerCase();
  return this.sortedTokens_VMP.filter(n => includes(n, s));
},

Функция, извлекающая вложенное значение по строке, где ключи разделены точками:

const getNested = (root, path) => path
  .split('.')
  .reduce((p, c) => p != null ? p[c] : p, root);

Используем её в вычисляемом свойстве, представляющем отсортированные данные, если попадается nullish значение, будем загонять соответствующий элемент в конец:

sortedTokens_VMP() {
  const reverse = this.sort.reverse ? -1 : 1;
  return this.tokens_VMP
    .map(n => [ getNested(n, this.sort.key), n ])
    .sort(([a], [b]) => reverse * (
      a == null ?  Infinity :
      b == null ? -Infinity :
      a < b     ?        -1 :
      a > b     ?         1 :
                          0
    ))
    .map(n => n[1]);
},
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@nurdus
А computed не так должен выглядеть?
computed: {
  sortedTokens_VMP: function () {
    //...
  },
  filteredTokens_VMP: function () {
    //...
  }
},
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы