Shekh Saifuddin
Shekh Saifuddin

Reputation: 518

Default props value are not selected in vue3 options api

I created a select2 wrapper in vue3 with options API everything working fine but the problem is that when getting values from calling API it's not selected the default value in the select2 option. but when I created a static array of objects it does. I don't know why it's working when it comes from the API

Parent Component

Here you can I passed the static options array in options props and my selected value is 2 and it's selected in my Select2 component, but when passed formattedCompanies it's not which is the same format as the static options array then why is not selected any reason here..?

<template>
  <Form @submitted="store()" :processing="submitting">
     <div class="row">
        <div class="col-lg-6">
           <div class="form-group">
              <label>Company Name</label>

              <Select2
                :options="options"
                v-model="selected"
                placeholder="Select Company"
              />

              <ValidationError :errors="errors" error-key="name" />
           </div>
        </div>
     </div>
  </Form>
</template>


<script>
import Form from "@/components/Common/Form";
import Select2 from "@/components/Common/Select2";

export default {
    components: {
        Select2,
        Form
    },

    data() {
        return {
            selected : 2,

            companies : [],

            options: [ // static array

                { id: 1, text: 'hello' },
                { id: 2, text: 'hello2' },
                { id: 3, text: 'hello3' },
                { id: 4, text: 'hello4' },
                { id: 5, text: 'hello5' },
            ],
        }
    },

    mounted() {
        this.getAllMedicineCompanies()
    },

    computed:{
        formattedCompanies() {
            let arr = [];
            this.companies.forEach(item => {
                arr.push({id: item.id, text: item.name})
            });

            return arr;
        }
    },

    methods: {
        getAllMedicineCompanies(){
            axios.get('/api/get-data?provider=companies')
                .then(({ data }) => {
                    this.companies = data
                })
        },
    }
}
</script>

Select2 Component

Here is what my select2 component look like, did I do anything wrong here, please anybody help me

<template>
    <select class="form-control">
        <slot/>
    </select>
</template>

<script>
export default {
    name: "Select2",

    props: {
        options: {
            type: [Array, Object],
            required: true
        },

        modelValue: [String, Number],

        placeholder: {
            type: String,
            default: "Search"
        },

        allowClear: {
            type: Boolean,
            default: true
        },
    },

    mounted() {
        const vm = this;

        $(this.$el)
            .select2({ // init select2
                data: this.options,
                placeholder: this.placeholder,
                allowClear: this.allowClear
            })
            .val(this.modelValue)
            .trigger("change")
            .on("change", function () { // emit event on change.
                vm.$emit("update:modelValue", this.value);
            });
    },

    watch: {
        modelValue(value) { // update value
            $(this.$el)
                .val(value)
                .trigger("change");
        },
        options(options) { // update options
            $(this.$el)
                .empty()
                .select2({data: options});
        },
    },

    destroyed() {
        $(this.$el)
            .off()
            .select2("destroy");
    }
}
</script>

Upvotes: 0

Views: 989

Answers (2)

Shekh Saifuddin
Shekh Saifuddin

Reputation: 518

The problem was that my parent component and Select2 component mounted at the same time that's why my computed value is not initialized so the selected value is not selected in the option,

problem solved by setTimeOut function in mounted like this

Select2 Component

<script>
mounted() {
  const vm = this;

   setTimeout(() => {
      $(this.$el)
      .select2({ // init select2
         data: this.options,
         placeholder: this.placeholder,
         allowClear: this.allowClear
      })
      .val(this.modelValue)
      .trigger("change")
      .on("change", function () { // emit event on change.
         vm.$emit("update:modelValue", this.value);
      });
   }, 500)
},
</script>

Upvotes: 0

gguney
gguney

Reputation: 2653

Probably when this Select2 mounted there is no companies. It is empty array after that it will make API call and it it populates options field and clear all options.

Make:

        companies : null,

Change it to

     <Select2
            v-if="formattedCompanies"
            :options="formattedCompanies"
            v-model="selected"
            placeholder="Select Company"
          />

It should be like this:

<template>
  <Form @submitted="store()" :processing="submitting">
     <div class="row">
        <div class="col-lg-6">
           <div class="form-group">
              <label>Company Name</label>


              <Select2
                  v-if="formattedCompanies"
                  :options="formattedCompanies"
                  v-model="selected"
                  placeholder="Select Company"
             />

              <ValidationError :errors="errors" error-key="name" />
           </div>
        </div>
     </div>
  </Form>
</template>


<script>
import Form from "@/components/Common/Form";
import Select2 from "@/components/Common/Select2";

export default {
    components: {
        Select2,
        Form
    },

    data() {
        return {
            selected : 2,

            companies : null,

            options: [ // static array

                { id: 1, text: 'hello' },
                { id: 2, text: 'hello2' },
                { id: 3, text: 'hello3' },
                { id: 4, text: 'hello4' },
                { id: 5, text: 'hello5' },
            ],
        }
    },

    mounted() {
        this.getAllMedicineCompanies()
    },

    computed:{
        formattedCompanies() {
            let arr = [];
            this.companies.forEach(item => {
                arr.push({id: item.id, text: item.name})
            });

            return arr;
        }
    },

    methods: {
        getAllMedicineCompanies(){
            axios.get('/api/get-data?provider=companies')
                .then(({ data }) => {
                    this.companies = data
                })
        },
    }
}
</script>

Upvotes: 1

Related Questions