Bootstrap vue select sending old value

Viewed 7033

I got this select code based on vue bootstrap:

<b-form-select v-model="selectedgroup" class="mb-3"  @change="searchSubGroup()">
    <option :value="null">Select a group</option>
    <option v-for="group in groupItem" :value="group.id">
        {{group.nome}}
    </option>
</b-form-select>  

When the searchSubGroup() method is called by @change event, the @change event pass a old value of selectedgroup. Example: If i click in option with value = 1 first, the method will call selectedgroup as null, then if i click again in another option with value = 2, the method will call selectedgroup as 1.

searchSubGroup(){ 
  this.axios.get("http://chart.solutions/public/api/produto/subgroup/search/" + this.selectedgroup + "/").then(response => {
        if (response.data.erro) {
            //console.log("subgroup doesnt exist")
        }else{
            this.subGroupItem = response.data;
        }
    })
} 
3 Answers

You need to remove the () from the @change call as such:

@change="searchSubGroup"

If you leave the () set, then the function is getting called when the component is getting build and the "selectedgroup" is still not defined, thus calling with null

v-model works based on @change so the event is getting fired twice. The selectedGroup method is getting called BEFORE the change method that updates the v-model data. Which is why the value was the "old one".

Even though the other answer is still a correct way of avoiding the issue, it does not explain exactly why this is happening.

Heres another solution:

  1. Remove your @change call from the b-form-select
  2. Add a "watched" property

    watch: { selectedgroup(value) { this.searchSubGroup(); //OR you could remove the method and just call axios here }) }

You should call your searchSubGroup method without the parentheses. This will automatically pass the newly selected value to your method ..

<b-form-select v-model="selectedgroup" class="mb-3"  @change="searchSubGroup">
    <option :value="null">Select a group</option>
    <option v-for="group in groupItem" :value="group.id">
        {{group.nome}}
    </option>
</b-form-select>

Then in your method you should do the following ..

searchSubGroup(value){ 
  this.axios.get("http://chart.solutions/public/api/produto/subgroup/search/" + value + "/").then(response => {
        if (response.data.erro) {
            //console.log("subgroup doesnt exist")
        }else{
            this.subGroupItem = response.data;
        }
    })
} 

You could use @input instead of @change event because @input="searchSubGroup" returns the current selected item

new Vue({
  el: '#app',

  data() {
    return {
      selected: null,
      options: [{
          value: null,
          text: 'Please select some item'
        },
        {
          value: 'a',
          text: 'This is option a'
        },
        {
          value: 'b',
          text: 'Default Selected Option b'
        },
        {
          value: 'c',
          text: 'This is option c'
        },
        {
          value: 'd',
          text: 'This one is disabled',
          disabled: true
        },
        {
          value: 'e',
          text: 'This is option e'
        },
        {
          value: 'e',
          text: 'This is option f'
        }
      ]
    }
  },
  methods: {
    choose() {
      console.log(this.selected)
    }
  }

});
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
  <link rel="stylesheet" href="style.css">
  <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
  <link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />

  <!-- Add this after vue.js -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
  <script src="//unpkg.com/babel-polyfill@latest/dist/polyfill.min.js"></script>
  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
  <script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>

</head>

<body>

  <div id="app">

    <b-form-select v-model="selected" :options="options" class="mb-3" @input="choose">
    </b-form-select>
    <div>Selected: <strong>{{ selected }}</strong></div>
  </div>

  <script src="script.js"></script>
</body>

</html>

Related