Cannot read properties of undefined (reading 'toLowerCase')

1.7k Views Asked by At

I am creating a searching input using Vue and and I made a method to check if each item should be visible or not and compare the current user input with the data of the item, and return true or false. The problem I have with the console, it shows me an Error related to "toLowerCase". please some help and advice. Thanks in advance.

<div
  v-for="item in itemList"
  :key="item.name"
  class="dropdown-item"
  v-show="itemVisible(item)"
 />

export default {
  name: "Demo",
  data() {
    return {
      inputValue: "",
      itemList: [],
      selectedItem: {},
    };
  },
itemVisible(item) {
  let currentName = item.name.toLowerCase();
  let currentInput = this.inputValue.toLowerCase();
  return currentName.includes(currentInput);
 }
}
2

There are 2 best solutions below

0
InvisibleGorilla On

It looks like the itemVisible(item) function should have been put inside of the methods object but event then it probably would not work as you expected because it would only get executed once on the initial render.

You probably want to watch the inputValue parameter and then go and execute the itemVisible() method on every item of selectedItems and save the data about visibility directly to the item or in a parallel data structure.

0
Joeri On

I would do something like this.

<template>
    <ul v-for="(item, idx) in itemList" :key="`key-${idx}`">
        <li class="dropdown-item" v-show="itemVisible(item)">
            {{ item.name }}
        </li>
    </ul>
</template>
<script>
export default {
    name: "Demo",

    data() {
        return {
            inputValue: "i",
            itemList: [
                { name: 'hi' },
                { name: 'by' },
            ],
            selectedItem: {},
        };
    },

    methods() {
        itemVisible(item) {
            let currentName  = item.name.toLowerCase();
            let currentInput = this.inputValue.toLowerCase();
            return currentName.includes(currentInput);
        }
    }
}
</script>

If you don't want ul/li you can swap ul with template and li with div

<template ...loop... > <div class="..."> {{ item.name }} </div> </template>