Paolo Resteghini
Paolo Resteghini

Reputation: 432

How to use an object not an array for an autocomplete form

I am new to Vue JS and having a mind blank when I've been creating my first Auto complete comp with VueCLI.

Here is the working code with an array: https://pastebin.com/a8AL8MkD

filterStates() {
  this.filteredStates = this.states.filter(state => {
    return state.toLowerCase().startsWith(this.state.toLowerCase())
  })
},

I am now trying to get it to work with JSON so I can use axios to get the data.

In the filterStates method I understand I need to get the name of the item and do the lowercase on that, but it keeps erroring out when I try this: https://pastebin.com/HPYyr9QH

filterStates() {
  this.filteredStates = this.states.filter(state => {
    return state.name.toLowerCase().startsWith(this.state.name.toLowerCase())
  })
},

Vue is erroring this:

[Vue warn]: Error in v-on handler: "TypeError: state.toLowerCase is not a function"

Do I need to pass in a key or something to identify each record?

Upvotes: 1

Views: 192

Answers (1)

BTL
BTL

Reputation: 4656

Let's take your second pastebin :

<script>
import PageBanner from '@/components/PageBanner.vue'
export default {
  components: {
    PageBanner
  },
  data() {
    return {
      state: '',
      modal: false,
      states: [
        {
          id: 1,
          name: 'Alaska'
        },
        {
          id: 2,
          name: 'Alabama'
        },
        {
          id: 3,
          name: 'Florida'
        }
      ],
      filteredStates: []
    }
  },
  methods: {
    filterStates() {
      this.filteredStates = this.states.filter(state => {
        return state.name.toLowerCase().startsWith(this.state.name.toLowerCase())
      })
    },
    setState(state) {
      this.state = state
      this.modal = false
    }
  }
}
</script>

You are calling : this.state.name.toLowerCase(). But this.state returns '' initially. So this.state.name is undefined.

You should initialize this.state with an object :

data() {
    return {
      state: {
        name: ''
      }
      ...

EDIT 17/03/2020 Here is another working solution :

What I did :

  • state is a string again. so I check this.state.toLowerCase()
  • In the setState function, I just pass the name : this.state = state.name
  • And to fix another error I changed this line : :key="filteredState.id" because a key should not be an object
<template>
  <div>
    <div class="AboutUs">
      <PageBanner>
        <template slot="title">Search</template>
      </PageBanner>
      <div class="container-fluid tarms-conditions">
        <div class="row">
          <div class="container">
            <input
              id
              v-model="state"
              type="text"
              name
              autocomplete="off"
              class="form-control z-10"
              placeholder="Search for a state..."
              @input="filterStates"
              @focus="modal = true"
            >
            <div
v-if="filteredStates && modal"
class="results z-10"
>
              <ul class="list">
                <li
                  v-for="filteredState in filteredStates"
                  :key="filteredState.id"
                  @click="setState(filteredState)"
                >
{{ filteredState }}
</li>
              </ul>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import PageBanner from '@/components/PageBanner.vue'
export default {
  components: {
    PageBanner
  },
  data () {
    return {
      state: '',
      modal: false,
      states: [
        {
          id: 1,
          name: 'Alaska'
        },
        {
          id: 2,
          name: 'Alabama'
        },
        {
          id: 3,
          name: 'Florida'
        }
      ],
      filteredStates: []
    }
  },
  methods: {
    filterStates () {
      this.filteredStates = this.states.filter(state => {
        return state.name.toLowerCase().startsWith(this.state.toLowerCase())
      })
    },
    setState (state) {
      this.state = state.name
      this.modal = false
    }
  }
}
</script>

Upvotes: 1

Related Questions