Using Props to Set Initial Value of VueMultiselect inside a Modal in Vue3

61 views Asked by At

I'm developing an app where I have a value from the parent file passed as a prop to the child file which is then used to set the default value of a VueMultiselect. It seems like I can access the prop without issues in the child file within the template or in functions I create in the script, however, I get null values when trying to access the prop outside of either of the two contexts I mentioned earlier. The expected behavior is that the VueMultiselect has a default letter (from A to D) that is preselected based on the prop by the time that the modal is opened, but nothing is chosen when I actually do so. Please see the code below, thank you!

App.vue

<template>
  <div>
    <button
      type="button"
      class="btn btn-outline-primary"
      data-bs-target="#resultModal"
      data-bs-toggle="modal"
    >
    Click Me!
    </button>
    <Test :letter="letter" />
  </div>
</template>

<script>
import Test from './components/Test.vue'

export default {
  name: 'app',
  components: {
    Test
  },
  mounted(){
      console.log(this.generateRandomLetter());
      this.letter = this.generateRandomLetter();
    },
  data() {
    return {
      letter: ''
    };
  },
  methods: {
    generateRandomLetter() {
      // Generate a random number between 0 and 3 (inclusive)
      const randomNumber = Math.floor(Math.random() * 4);

      // Convert the random number to a letter between A and D
      const randomLetter = String.fromCharCode('A'.charCodeAt(0) + randomNumber);

      return randomLetter;
    }
  }
}
</script>

<style scoped>
button {
  background: #26E6A4;
  border: 0;
  font-size: 16px;
  color: '#fff';
  padding: 10px;
  margin-left: 28px;
}
</style>

Test.vue

<template>
  <div
    class="modal fade"
    id="resultModal"
    tabindex="-1"
    role="dialog"
    aria-labelledby="resultModalLabel"
  >
  <div class="modal-dialog modal-dialog-centered modal-xl" role="document">
    <div class="modal-dialog">
    <div class="modal-content p-3">
    <VueMultiselect
            v-model="selectedLetter"
            :options="dataSet"
            :close-on-select="true"
            :show-labels="false"
            :searchable="false"
            placeholder="Select a letter"
    >
    </VueMultiselect>
    </div>
    </div>
    </div>
    </div>
  </template>
  
  <script>
  import VueMultiselect from 'vue-multiselect';
  import { ref } from 'vue';
  
  export default {
    name: 'Test',
    components: {
      VueMultiselect
    },
    props: ['letter'],
    setup(props) {
      const selectedLetter = ref(props.letter);
      console.log(selectedLetter.value);
  
      return {
        selectedLetter,
        dataSet: ['A', 'B', 'C', 'D']
      };
    }
  };
  </script>

  <style>
@import 'vue-multiselect/dist/vue-multiselect.css';
</style>
1

There are 1 answers

0
m.yoshih On

I was able to get this to work by adding the following code to Test.vue in setup(props):

    setup(props) {
      const selectedLetter = ref('');
      watch(() => props.letter, (currentValue, oldValue) => {
        console.log(currentValue);
        console.log(oldValue);
        selectedLetter.value = currentValue;
      });
      return {
        selectedLetter,
        dataSet: ['A', 'B', 'C', 'D']
      };
    }

so now I have the following for Test.vue:

<template>
  <div
    class="modal fade"
    id="resultModal"
    tabindex="-1"
    role="dialog"
    aria-labelledby="resultModalLabel"
  >
  <div class="modal-dialog modal-dialog-centered modal-xl" role="document">
    <div class="modal-dialog">
    <div class="modal-content p-3">
    <VueMultiselect
            v-model="selectedLetter"
            :options="dataSet"
            :close-on-select="true"
            :show-labels="false"
            :searchable="false"
            placeholder="Select a letter"
    >
    </VueMultiselect>
    </div>
    </div>
    </div>
    </div>
  </template>
  
  <script>
  import VueMultiselect from 'vue-multiselect';
  import { ref, watch } from 'vue';
  
  export default {
    name: 'Test',
    components: {
      VueMultiselect
    },
    props: ['letter'],
    setup(props) {
      const selectedLetter = ref('');
      watch(() => props.letter, (currentValue, oldValue) => {
        console.log(currentValue);
        console.log(oldValue);
        selectedLetter.value = currentValue;
      });
      return {
        selectedLetter,
        dataSet: ['A', 'B', 'C', 'D']
      };
    }
  };
  </script>

  <style>
@import 'vue-multiselect/dist/vue-multiselect.css';
</style>