Laravel 5.7, Обновите ‹options› в раскрывающемся списке с помощью Vue

Я пишу свой первый компонент Laravel Vue, и у меня есть эта ошибка в консоли.

[Предупреждение Vue]: вычисленное свойство "options" было назначено, но у него нет установщика.

Код состоит из двух раскрывающихся списков, одно с континентами, а другое с странами. Я хочу, чтобы при обновлении континента обновлялись страны.

Я просто скучаю по обновлению параметров второго выбора с обновленными значениями, которые у меня есть в this.countries.

После изменения континента переменная this.countries обновляется, но значения параметров выбора country_id не меняются. Я пробовал добавить вычислено, но получаю эту ошибку.

Что я делаю неправильно?

<template>
    <div>
        <div class="form-group continent_id">    
            <select name="continent_id" v-model="continent_selected" id="continent_id" class="selectpicker" data-live-search="false" title="Pick a continent" v-on:change="getAllCountries(continents)">
                <option v-if="continents.length>0" v-for="continent in continents" v-bind:value="continent.id">
                    {{ continent.name }}
                </option>
            </select>
        </div>

        <div class="form-group country_id">    
            <select name="country_id" v-model="country_selected" id="country_id" class="selectpicker" data-live-search="true" title="Pick a country">
                <option  v-for="(country, index) in countries" v-bind:value="country.id" >
                    {{ country.name }}
                </option>
            </select>
        </div>
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('Component mounted.');
            this.loadData();
        },
        data() {
            return {
                continents: [],
                countries: [],
                continent_selected: '',
                country_selected: '',
            }
       },
       computed: {
           get: function () {
               return this.countries;
           },
           set: function (newValue) {
               this.countries = newValue; 
           }
       },
       methods: {
            loadData: function() {
                axios.get('/api/continents')
                .then((response) => {
                    // handle success
                    this.continents = response.data.data;
                    this.getAllCountries(this.continents);
                })
                .catch((error) => {
                    // handle error
                    console.log(error);
                })
                .then(() => {
                    // always executed
                });
            },
            getAllCountries: function(continents) {
                console.log(this.continent_selected);
                console.log(continents);

                var j = 0;
                this.countries = [];

                for (var i = 0, len = continents.length; i < len; i++) {
                    if (!this.continent_selected){
                        for (var key in continents[i].active_countries) {
                            this.countries[j] = {id: continents[i].active_countries[key], name: key};
                            j++;
                        }
                    }
                    else{
                        console.log("continent selected: "+ this.continent_selected);
                        for (var key in continents[i].active_countries) {
                            if (continents[i].id == this.continent_selected){
                                this.countries[j] = {id: continents[i].active_countries[key], name: key};
                                j++;
                            }
                        }

                    }
                }
            }
        },
    }
</script>

person Davide Casiraghi    schedule 26.02.2019    source источник


Ответы (2)


В этой строке вы устанавливаете значение атрибута options:

this.options = this.options;

, но это свойство вычисляется:

computed: {
    options: function(event) {
        return this.countries
    }
},

В этом случае вы можете:

1) создайте вычисляемый сеттер: https://vuejs.org/v2/guide/computed.html#Computed-Setter

computed: {
    options: {
        get: function () {
            return this.countries;
        },
        set: function (newValue) {
            this.countries = newValue; 
        }
    }     
},

2) Установите значение напрямую:

this.countries = this.options;
person lmarqs    schedule 26.02.2019
comment
Я пробовал оба, ошибка исчезает, но один работает .. Второй раскрывающийся список еще не обновляется. - person Davide Casiraghi; 26.02.2019
comment
Я голосую за ваш вопрос, потому что он помогает мне избавиться от моей проблемы, заставляя меня искать решение. Спасибо за время, потраченное на мой вопрос! - person Davide Casiraghi; 01.03.2019

Я решил свою проблему, которая в основном была связана с методом вычисляемого набора переменной optionCountries.

Раскрывающийся список не обновлялся, потому что в нем используется Bootsrap Select, поэтому для отображения новых параметров его необходимо обновить.

Я также понял, что мне нужно добавить тайм-аут к запросу на обновление.

Это последний код.

<template>
    <div>
        <div class="form-group continent_id">    
            <select name="continent_id" v-model="continent_selected" id="continent_id" class="selectpicker" data-live-search="false" title="Pick a continent" v-on:change="getAllCountries(continents)">
                <option v-if="continents.length>0" v-for="continent in continents" v-bind:value="continent.id">
                    {{ continent.name }}
                </option>
            </select>
        </div>

        <div class="form-group country_id">    
            <select name="country_id" v-model="country_selected" id="country_id" class="selectpicker" data-live-search="true" title="Pick a country">
                <option  v-for="(country, index) in optionCountries" v-bind:value="country.id" >
                    {{ country.name }}
                </option>  
            </select>
        </div>
    </div>
</template>

<script>
    export default {
        mounted() {
            console.log('Component mounted.');
            this.loadData();
        },
        data() {
            return {
                continents: [],  
                countries: [],
                continent_selected: '',
                country_selected: '',
            }
       },
       computed: {
           optionCountries:{   
               get: function () {
                    return this.countries;
                },
                set: function (newValue) {
                    this.countries = newValue;
                    setTimeout(() => {
                       jQuery('.selectpicker').selectpicker('refresh');
                    }, 500);
                }
            } 
        },

       methods: {
            loadData: function() {  
                axios.get('/api/continents')
                .then((response) => {
                    // handle success
                    this.continents = response.data.data;
                    this.getAllCountries(this.continents);
                })
                .catch((error) => {
                    // handle error
                    console.log(error);
                })
                .then(() => {
                    // always executed
                });
            },
            getAllCountries: function(continents) {                
                var j = 0;
                this.countries = [];

                for (var i = 0, len = continents.length; i < len; i++) {
                    if (!this.continent_selected){
                        for (var key in continents[i].active_countries) {
                            this.countries[j] = {id: continents[i].active_countries[key], name: key};
                            j++;
                        }
                    }
                    else{
                        for (var key in continents[i].active_countries) {
                            if (continents[i].id == this.continent_selected){
                                this.countries[j] = {id: continents[i].active_countries[key], name: key};
                                j++;
                            }
                        }
                        this.optionCountries = this.countries;
                    }
                }
            }
        },
    }
</script>
person Davide Casiraghi    schedule 27.02.2019