Home > Mobile >  Vue 3 : issue in getting onchange event from child component
Vue 3 : issue in getting onchange event from child component

Time:11-20

I made a component to provide a select including a button that reset the select to the initial state (no option selected). I get well the onchange event in parent when an option is selected but nothing when the reset button is clicked, although the select is reset. In my use case the list is still filtered even when nothing is selected

Here is the parent file :

<template>
  <liste-filter
            :nom="'marque'"
            :label="'Choose a make'"
            :liste="marques"
            v-model="selMarque"
            @change="changefilter"></liste-filter>
  <h1/>  
  <div v-for="vh in vehicules" :key="vh.lib" class="w-full">
    {{ vh.lib }}
  </div>

  <div v-if="vehicules.length === 0">The list is empty</div>

</template>

<script>
import ListeFilter from "./ListeFilter.vue"
  
export default {
  components: {
    ListeFilter
  },
  data() {
    return {
      marques:[{id:"Renault",libelle:"Renault"},{id:"Peugeot",libelle:"Peugeot"}],
      selMarque: "",
      vehicules: [],
      tabData:[{"lib":"Renault","modeles":[{"lib":"Clio"},{"lib":"Captur"}]},{"lib":"Peugeot","modeles":[{"lib":"208"},{"lib":"308"},{"lib":"3008"}]}]
    };
  },
  methods: {
    changefilter() {
      this.vehicules = [];
      for (var i = 0; i < this.tabData.length; i  ) {
        if(this.selMarque != "" && this.tabData[i].lib == this.selMarque) {
          this.vehicules = this.tabData[i].modeles;
        }
      }
    }
  }
}
</script>

And here is the component file ListeFilter.vue :

<template>
  <span class="relative">
    <select
      :name="nom"
      :id="nom"
      :label="label"
      v-model="sel"
      class="w-64 text-sm"
    >
      <option disabled value="">{{ label }}</option>
      <option v-for="elem in liste" :value="elem.id" :key="elem.id">
        {{ elem.libelle }}
      </option>
    </select>
    <button
      v-show="sel"
      @click="reset"
    >X</button>
  </span>
</template>

<script>
export default {
  props: ["nom", "label", "liste", "modelValue"],
  emits: ["update:modelValue"],
  computed: {
    sel: {
      get() {
        return this.modelValue;
      },
      set(value) {
        this.$emit("update:modelValue", value);
      },
    },
  },
  methods: {
    reset() {
      this.sel = ""
    },
  },
};
</script>

I also made a Vue SFC Playground to test HERE

Thanks in advance for your help.

PS : if you know a component that does the same I take it ! (vue-select does not seem Vue 3 compliant)

CodePudding user response:

I think you should be listening for the @update:modelValue="changefilter" event instead of the change event @change="changefilter". It's documented here. https://v3.vuejs.org/guide/migration/v-model.html#overview

Try changing your App.vue to this.

Here is a Playground

<template>
  <liste-filter
                :nom="'marque'"
                :label="'Choose a mark'"
                :liste="marques"
                v-model="selMarque"                
                @update:modelValue="changefilter"
                >
  </liste-filter>
  <h1/>  
  <div v-for="vh in vehicules" :key="vh.lib" >
    {{ vh.lib }}
  </div>

  <div v-if="vehicules.length === 0">The list is empty</div>

</template>

<script>
import ListeFilter from "./ListeFilter.vue"
  
export default {
  components: {
    ListeFilter
  },
  data() {
    return {
      marques:[{id:"Renault",libelle:"Renault"},{id:"Peugeot",libelle:"Peugeot"}],
      selMarque: "",
      vehicules: [],
      tabData:[{"lib":"Renault","modeles":[{"lib":"Clio"},{"lib":"Captur"}]},{"lib":"Peugeot","modeles":[{"lib":"208"},{"lib":"308"},{"lib":"3008"}]}]
    };
  },
  methods: {
    changefilter() {
      console.log('change happened');
      this.vehicules = [];
      for (var i = 0; i < this.tabData.length; i  ) {
        if(this.selMarque != "" && this.tabData[i].lib == this.selMarque) {
          this.vehicules = this.tabData[i].modeles;
        }
      }
    }
  }
}
</script>
  • Related