Tanmay
Tanmay

Reputation: 3159

Resetting previous selection in VueJS

I have two custom select input fields in a form: Country and City. City is depended on the Country, as you may have already guessed. So when a user selects a country:

Scenario: From the country selectbox, I selected United States. From the city selectbox I selected Texas (which has the value: 6). Now if I go back to the first select box and change the country to United Kingdom, it will automatically select the 6th city of UK based on the previous selection.

Here is what I am doing:

<custom-select type="select" name="country_id" @change="selectCountry">
   <option disabled selected>Choose a Country</option>
   <option v-for="country in countries" :value="country.id">@{{ country.name }}</option>
</custom-select>

<custom-select type="select" name="city_id" @change="selectCity">
   <option disabled selected>Choose a City</option>
   <option v-for="city in cities" :value="city.id">@{{ city.name }}</option>
</custom-select>

How do I reset the city selection everytime I select a country?

Upvotes: 3

Views: 2983

Answers (2)

Roland
Roland

Reputation: 27729

I am going to show how to do that using a simple example:

You can also, see it in action by clicking here

<div id="app">
  <select v-model="selectedState" @change="stateChanged">
    <option :value="null">Select State</option>
    <option
      v-for="state in states"
      :key="state.id"
     :value="state.id"
     >
       {{state.text}}
     </option>
  </select>

  <select v-model="selectedCity">
    <option :value="null">Select City</option>
    <option
      v-for="city in citiesDependOnSelectedState"
      :key="city.id"
      :value="city.id"
     >
       {{city.text}}
     </option>
  </select>
</div>

new Vue({
  el: "#app",
  data: {
    states: [
      { text: "Albania", id: 1 },
      { text: "Greece", id: 2 },
      { text: "Italy", id: 3 },
      { text: "Germany", id: 4 }
    ],
    cities: [
        { text: "Tirana", id: 1, state: 1 },
      { text: "Vlora", id: 2, state: 1 },
      { text: "Thessaloniki", id: 3, state: 2 },
      { text: "Athens", id: 4, state: 2 },
      { text: "Berlin", id: 5, state: 4 },
      { text: "Hamburg", id: 6, state: 4 },
      { text: "Rome", id: 7, state: 3 },
      { text: "Milano", id: 8, state: 3 }
    ],
    selectedState: null,
    selectedCity: null
  },
  computed: {
    citiesDependOnSelectedState() {
        return this.cities.filter(el => el.state === this.selectedState)
    }
  },
  methods: {
    stateChanged() {
        this.selectedCity = null
    }
  }
})

Upvotes: 1

dfsq
dfsq

Reputation: 193261

The thing is that Vue tries to reuse existing HTML in order to speed up rendering. In your case it chooses not to rerender HTML for select boxes, and it just changes text content of options. Simple way to say force rerendering is to use different key prop for city select depending on selected country:

<custom-select type="select" :key="selectedCountryId" name="city_id" @change="selectCity">
   <option disabled selected>Choose a City</option>
   <option v-for="city in cities" :value="city.id">@{{ city.name }}</option>
</custom-select>

Note, I added :key="selectedCountryId" to the city select. You will need to create this selectedCountryId property in selectCountry method, for example:

selectCountry (e) {
  this.selectedCountryId = e.target.selectedIndex
  axios.get(...)
}

Upvotes: 4

Related Questions